@ai-sdk/revai 3.0.51 → 3.0.52

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,517 +1,431 @@
1
- // src/revai-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/revai-transcription-model.ts
11
- import {
12
- AISDKError
13
- } from "@ai-sdk/provider";
14
- import {
15
- combineHeaders,
16
- convertBase64ToUint8Array,
17
- createJsonResponseHandler,
18
- mediaTypeToExtension,
19
- delay,
20
- getFromApi,
21
- parseProviderOptions,
22
- postFormDataToApi,
23
- serializeModelOptions,
24
- WORKFLOW_SERIALIZE,
25
- WORKFLOW_DESERIALIZE
26
- } from "@ai-sdk/provider-utils";
27
- import { z as z3 } from "zod/v4";
28
-
29
- // src/revai-error.ts
1
+ import { AISDKError, NoSuchModelError } from "@ai-sdk/provider";
2
+ import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, convertBase64ToUint8Array, createJsonErrorResponseHandler, createJsonResponseHandler, delay, getFromApi, loadApiKey, mediaTypeToExtension, parseProviderOptions, postFormDataToApi, serializeModelOptions, withUserAgentSuffix } from "@ai-sdk/provider-utils";
30
3
  import { z } from "zod/v4";
31
- import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
32
- var revaiErrorDataSchema = z.object({
33
- error: z.object({
34
- message: z.string(),
35
- code: z.number()
36
- })
4
+ //#region src/revai-error.ts
5
+ const revaiErrorDataSchema = z.object({ error: z.object({
6
+ message: z.string(),
7
+ code: z.number()
8
+ }) });
9
+ const revaiFailedResponseHandler = createJsonErrorResponseHandler({
10
+ errorSchema: revaiErrorDataSchema,
11
+ errorToMessage: (data) => data.error.message
37
12
  });
38
- var revaiFailedResponseHandler = createJsonErrorResponseHandler({
39
- errorSchema: revaiErrorDataSchema,
40
- errorToMessage: (data) => data.error.message
13
+ //#endregion
14
+ //#region src/revai-transcription-model-options.ts
15
+ const revaiTranscriptionModelOptionsSchema = z.object({
16
+ /**
17
+ * Optional metadata string to associate with the transcription job.
18
+ */
19
+ metadata: z.string().nullish(),
20
+ /**
21
+ * Configuration for webhook notifications when job is complete.
22
+ */
23
+ notification_config: z.object({
24
+ /**
25
+ * URL to send the notification to.
26
+ */
27
+ url: z.string(),
28
+ /**
29
+ * Optional authorization headers for the notification request.
30
+ */
31
+ auth_headers: z.object({ Authorization: z.string() }).nullish()
32
+ }).nullish(),
33
+ /**
34
+ * Number of seconds after which the job will be automatically deleted.
35
+ */
36
+ delete_after_seconds: z.number().nullish(),
37
+ /**
38
+ * Whether to include filler words and false starts in the transcription.
39
+ */
40
+ verbatim: z.boolean().optional(),
41
+ /**
42
+ * Whether to prioritize the job for faster processing.
43
+ */
44
+ rush: z.boolean().nullish().default(false),
45
+ /**
46
+ * Whether to run the job in test mode.
47
+ */
48
+ test_mode: z.boolean().nullish().default(false),
49
+ /**
50
+ * Specific segments of the audio to transcribe.
51
+ */
52
+ segments_to_transcribe: z.array(z.object({
53
+ /**
54
+ * Start time of the segment in seconds.
55
+ */
56
+ start: z.number(),
57
+ /**
58
+ * End time of the segment in seconds.
59
+ */
60
+ end: z.number()
61
+ })).nullish(),
62
+ /**
63
+ * Names to assign to speakers in the transcription.
64
+ */
65
+ speaker_names: z.array(z.object({
66
+ /**
67
+ * Display name for the speaker.
68
+ */
69
+ display_name: z.string() })).nullish(),
70
+ /**
71
+ * Whether to skip speaker diarization.
72
+ */
73
+ skip_diarization: z.boolean().nullish().default(false),
74
+ /**
75
+ * Whether to skip post-processing steps.
76
+ */
77
+ skip_postprocessing: z.boolean().nullish().default(false),
78
+ /**
79
+ * Whether to skip adding punctuation to the transcription.
80
+ */
81
+ skip_punctuation: z.boolean().nullish().default(false),
82
+ /**
83
+ * Whether to remove disfluencies (um, uh, etc.) from the transcription.
84
+ */
85
+ remove_disfluencies: z.boolean().nullish().default(false),
86
+ /**
87
+ * Whether to remove atmospheric sounds from the transcription.
88
+ */
89
+ remove_atmospherics: z.boolean().nullish().default(false),
90
+ /**
91
+ * Whether to filter profanity from the transcription.
92
+ */
93
+ filter_profanity: z.boolean().nullish().default(false),
94
+ /**
95
+ * Number of speaker channels in the audio.
96
+ */
97
+ speaker_channels_count: z.number().nullish(),
98
+ /**
99
+ * Expected number of speakers in the audio.
100
+ */
101
+ speakers_count: z.number().nullish(),
102
+ /**
103
+ * Type of diarization to use.
104
+ */
105
+ diarization_type: z.enum(["standard", "premium"]).nullish().default("standard"),
106
+ /**
107
+ * ID of a custom vocabulary to use for the transcription.
108
+ */
109
+ custom_vocabulary_id: z.string().nullish(),
110
+ /**
111
+ * Custom vocabularies to use for the transcription.
112
+ */
113
+ custom_vocabularies: z.array(z.object({})).optional(),
114
+ /**
115
+ * Whether to strictly enforce custom vocabulary.
116
+ */
117
+ strict_custom_vocabulary: z.boolean().optional(),
118
+ /**
119
+ * Configuration for generating a summary of the transcription.
120
+ */
121
+ summarization_config: z.object({
122
+ /**
123
+ * Model to use for summarization.
124
+ */
125
+ model: z.enum(["standard", "premium"]).nullish().default("standard"),
126
+ /**
127
+ * Format of the summary.
128
+ */
129
+ type: z.enum(["paragraph", "bullets"]).nullish().default("paragraph"),
130
+ /**
131
+ * Custom prompt for the summarization.
132
+ */
133
+ prompt: z.string().nullish()
134
+ }).nullish(),
135
+ /**
136
+ * Configuration for translating the transcription.
137
+ */
138
+ translation_config: z.object({
139
+ /**
140
+ * Target languages for translation.
141
+ */
142
+ target_languages: z.array(z.object({
143
+ /**
144
+ * Language code for translation target.
145
+ */
146
+ language: z.enum([
147
+ "en",
148
+ "en-us",
149
+ "en-gb",
150
+ "ar",
151
+ "pt",
152
+ "pt-br",
153
+ "pt-pt",
154
+ "fr",
155
+ "fr-ca",
156
+ "es",
157
+ "es-es",
158
+ "es-la",
159
+ "it",
160
+ "ja",
161
+ "ko",
162
+ "de",
163
+ "ru"
164
+ ]) })),
165
+ /**
166
+ * Model to use for translation.
167
+ */
168
+ model: z.enum(["standard", "premium"]).nullish().default("standard")
169
+ }).nullish(),
170
+ /**
171
+ * Language of the audio content.
172
+ */
173
+ language: z.string().nullish().default("en"),
174
+ /**
175
+ * Whether to perform forced alignment.
176
+ */
177
+ forced_alignment: z.boolean().nullish().default(false)
41
178
  });
42
-
43
- // src/revai-transcription-model-options.ts
44
- import { z as z2 } from "zod/v4";
45
- var revaiTranscriptionModelOptionsSchema = z2.object({
46
- /**
47
- * Optional metadata string to associate with the transcription job.
48
- */
49
- metadata: z2.string().nullish(),
50
- /**
51
- * Configuration for webhook notifications when job is complete.
52
- */
53
- notification_config: z2.object({
54
- /**
55
- * URL to send the notification to.
56
- */
57
- url: z2.string(),
58
- /**
59
- * Optional authorization headers for the notification request.
60
- */
61
- auth_headers: z2.object({
62
- Authorization: z2.string()
63
- }).nullish()
64
- }).nullish(),
65
- /**
66
- * Number of seconds after which the job will be automatically deleted.
67
- */
68
- delete_after_seconds: z2.number().nullish(),
69
- /**
70
- * Whether to include filler words and false starts in the transcription.
71
- */
72
- verbatim: z2.boolean().optional(),
73
- /**
74
- * Whether to prioritize the job for faster processing.
75
- */
76
- rush: z2.boolean().nullish().default(false),
77
- /**
78
- * Whether to run the job in test mode.
79
- */
80
- test_mode: z2.boolean().nullish().default(false),
81
- /**
82
- * Specific segments of the audio to transcribe.
83
- */
84
- segments_to_transcribe: z2.array(
85
- z2.object({
86
- /**
87
- * Start time of the segment in seconds.
88
- */
89
- start: z2.number(),
90
- /**
91
- * End time of the segment in seconds.
92
- */
93
- end: z2.number()
94
- })
95
- ).nullish(),
96
- /**
97
- * Names to assign to speakers in the transcription.
98
- */
99
- speaker_names: z2.array(
100
- z2.object({
101
- /**
102
- * Display name for the speaker.
103
- */
104
- display_name: z2.string()
105
- })
106
- ).nullish(),
107
- /**
108
- * Whether to skip speaker diarization.
109
- */
110
- skip_diarization: z2.boolean().nullish().default(false),
111
- /**
112
- * Whether to skip post-processing steps.
113
- */
114
- skip_postprocessing: z2.boolean().nullish().default(false),
115
- /**
116
- * Whether to skip adding punctuation to the transcription.
117
- */
118
- skip_punctuation: z2.boolean().nullish().default(false),
119
- /**
120
- * Whether to remove disfluencies (um, uh, etc.) from the transcription.
121
- */
122
- remove_disfluencies: z2.boolean().nullish().default(false),
123
- /**
124
- * Whether to remove atmospheric sounds from the transcription.
125
- */
126
- remove_atmospherics: z2.boolean().nullish().default(false),
127
- /**
128
- * Whether to filter profanity from the transcription.
129
- */
130
- filter_profanity: z2.boolean().nullish().default(false),
131
- /**
132
- * Number of speaker channels in the audio.
133
- */
134
- speaker_channels_count: z2.number().nullish(),
135
- /**
136
- * Expected number of speakers in the audio.
137
- */
138
- speakers_count: z2.number().nullish(),
139
- /**
140
- * Type of diarization to use.
141
- */
142
- diarization_type: z2.enum(["standard", "premium"]).nullish().default("standard"),
143
- /**
144
- * ID of a custom vocabulary to use for the transcription.
145
- */
146
- custom_vocabulary_id: z2.string().nullish(),
147
- /**
148
- * Custom vocabularies to use for the transcription.
149
- */
150
- custom_vocabularies: z2.array(z2.object({})).optional(),
151
- /**
152
- * Whether to strictly enforce custom vocabulary.
153
- */
154
- strict_custom_vocabulary: z2.boolean().optional(),
155
- /**
156
- * Configuration for generating a summary of the transcription.
157
- */
158
- summarization_config: z2.object({
159
- /**
160
- * Model to use for summarization.
161
- */
162
- model: z2.enum(["standard", "premium"]).nullish().default("standard"),
163
- /**
164
- * Format of the summary.
165
- */
166
- type: z2.enum(["paragraph", "bullets"]).nullish().default("paragraph"),
167
- /**
168
- * Custom prompt for the summarization.
169
- */
170
- prompt: z2.string().nullish()
171
- }).nullish(),
172
- /**
173
- * Configuration for translating the transcription.
174
- */
175
- translation_config: z2.object({
176
- /**
177
- * Target languages for translation.
178
- */
179
- target_languages: z2.array(
180
- z2.object({
181
- /**
182
- * Language code for translation target.
183
- */
184
- language: z2.enum([
185
- "en",
186
- "en-us",
187
- "en-gb",
188
- "ar",
189
- "pt",
190
- "pt-br",
191
- "pt-pt",
192
- "fr",
193
- "fr-ca",
194
- "es",
195
- "es-es",
196
- "es-la",
197
- "it",
198
- "ja",
199
- "ko",
200
- "de",
201
- "ru"
202
- ])
203
- })
204
- ),
205
- /**
206
- * Model to use for translation.
207
- */
208
- model: z2.enum(["standard", "premium"]).nullish().default("standard")
209
- }).nullish(),
210
- /**
211
- * Language of the audio content.
212
- */
213
- language: z2.string().nullish().default("en"),
214
- /**
215
- * Whether to perform forced alignment.
216
- */
217
- forced_alignment: z2.boolean().nullish().default(false)
218
- });
219
-
220
- // src/revai-transcription-model.ts
221
- var RevaiTranscriptionModel = class _RevaiTranscriptionModel {
222
- constructor(modelId, config) {
223
- this.modelId = modelId;
224
- this.config = config;
225
- this.specificationVersion = "v4";
226
- }
227
- get provider() {
228
- return this.config.provider;
229
- }
230
- static [WORKFLOW_SERIALIZE](model) {
231
- return serializeModelOptions({
232
- modelId: model.modelId,
233
- config: model.config
234
- });
235
- }
236
- static [WORKFLOW_DESERIALIZE](options) {
237
- return new _RevaiTranscriptionModel(options.modelId, options.config);
238
- }
239
- async getArgs({
240
- audio,
241
- mediaType,
242
- providerOptions
243
- }) {
244
- const warnings = [];
245
- const revaiOptions = await parseProviderOptions({
246
- provider: "revai",
247
- providerOptions,
248
- schema: revaiTranscriptionModelOptionsSchema
249
- });
250
- const formData = new FormData();
251
- const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array(audio)]);
252
- const fileExtension = mediaTypeToExtension(mediaType);
253
- formData.append(
254
- "media",
255
- new File([blob], "audio", { type: mediaType }),
256
- `audio.${fileExtension}`
257
- );
258
- const transcriptionModelOptions = {
259
- transcriber: this.modelId
260
- };
261
- if (revaiOptions) {
262
- const formDataConfig = {
263
- metadata: revaiOptions.metadata ?? void 0,
264
- notification_config: revaiOptions.notification_config ?? void 0,
265
- delete_after_seconds: revaiOptions.delete_after_seconds ?? void 0,
266
- verbatim: revaiOptions.verbatim ?? void 0,
267
- rush: revaiOptions.rush ?? void 0,
268
- test_mode: revaiOptions.test_mode ?? void 0,
269
- segments_to_transcribe: revaiOptions.segments_to_transcribe ?? void 0,
270
- speaker_names: revaiOptions.speaker_names ?? void 0,
271
- skip_diarization: revaiOptions.skip_diarization ?? void 0,
272
- skip_postprocessing: revaiOptions.skip_postprocessing ?? void 0,
273
- skip_punctuation: revaiOptions.skip_punctuation ?? void 0,
274
- remove_disfluencies: revaiOptions.remove_disfluencies ?? void 0,
275
- remove_atmospherics: revaiOptions.remove_atmospherics ?? void 0,
276
- filter_profanity: revaiOptions.filter_profanity ?? void 0,
277
- speaker_channels_count: revaiOptions.speaker_channels_count ?? void 0,
278
- speakers_count: revaiOptions.speakers_count ?? void 0,
279
- diarization_type: revaiOptions.diarization_type ?? void 0,
280
- custom_vocabulary_id: revaiOptions.custom_vocabulary_id ?? void 0,
281
- custom_vocabularies: revaiOptions.custom_vocabularies ?? void 0,
282
- strict_custom_vocabulary: revaiOptions.strict_custom_vocabulary ?? void 0,
283
- summarization_config: revaiOptions.summarization_config ?? void 0,
284
- translation_config: revaiOptions.translation_config ?? void 0,
285
- language: revaiOptions.language ?? void 0,
286
- forced_alignment: revaiOptions.forced_alignment ?? void 0
287
- };
288
- for (const key in formDataConfig) {
289
- const value = formDataConfig[key];
290
- if (value !== void 0) {
291
- transcriptionModelOptions[key] = value;
292
- }
293
- }
294
- }
295
- formData.append("config", JSON.stringify(transcriptionModelOptions));
296
- return {
297
- formData,
298
- warnings
299
- };
300
- }
301
- async doGenerate(options) {
302
- const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
303
- const { formData, warnings } = await this.getArgs(options);
304
- const { value: submissionResponse } = await postFormDataToApi({
305
- url: this.config.url({
306
- path: "/speechtotext/v1/jobs",
307
- modelId: this.modelId
308
- }),
309
- headers: combineHeaders(this.config.headers?.(), options.headers),
310
- formData,
311
- failedResponseHandler: revaiFailedResponseHandler,
312
- successfulResponseHandler: createJsonResponseHandler(
313
- revaiTranscriptionJobResponseSchema
314
- ),
315
- abortSignal: options.abortSignal,
316
- fetch: this.config.fetch
317
- });
318
- if (submissionResponse.status === "failed") {
319
- throw new AISDKError({
320
- message: "Failed to submit transcription job to Rev.ai",
321
- name: "TranscriptionJobSubmissionFailed",
322
- cause: submissionResponse
323
- });
324
- }
325
- const jobId = submissionResponse.id;
326
- const timeoutMs = 60 * 1e3;
327
- const startTime = Date.now();
328
- const pollingInterval = 1e3;
329
- let jobResponse = submissionResponse;
330
- while (jobResponse.status !== "transcribed") {
331
- if (Date.now() - startTime > timeoutMs) {
332
- throw new AISDKError({
333
- message: "Transcription job polling timed out",
334
- name: "TranscriptionJobPollingTimedOut",
335
- cause: submissionResponse
336
- });
337
- }
338
- const pollingResult = await getFromApi({
339
- url: this.config.url({
340
- path: `/speechtotext/v1/jobs/${jobId}`,
341
- modelId: this.modelId
342
- }),
343
- validateUrl: false,
344
- headers: combineHeaders(this.config.headers?.(), options.headers),
345
- failedResponseHandler: revaiFailedResponseHandler,
346
- successfulResponseHandler: createJsonResponseHandler(
347
- revaiTranscriptionJobResponseSchema
348
- ),
349
- abortSignal: options.abortSignal,
350
- fetch: this.config.fetch
351
- });
352
- jobResponse = pollingResult.value;
353
- if (jobResponse.status === "failed") {
354
- throw new AISDKError({
355
- message: "Transcription job failed",
356
- name: "TranscriptionJobFailed",
357
- cause: jobResponse
358
- });
359
- }
360
- if (jobResponse.status !== "transcribed") {
361
- await delay(pollingInterval);
362
- }
363
- }
364
- const {
365
- value: transcriptionResult,
366
- responseHeaders,
367
- rawValue: rawResponse
368
- } = await getFromApi({
369
- url: this.config.url({
370
- path: `/speechtotext/v1/jobs/${jobId}/transcript`,
371
- modelId: this.modelId
372
- }),
373
- validateUrl: false,
374
- headers: combineHeaders(this.config.headers?.(), options.headers),
375
- failedResponseHandler: revaiFailedResponseHandler,
376
- successfulResponseHandler: createJsonResponseHandler(
377
- revaiTranscriptionResponseSchema
378
- ),
379
- abortSignal: options.abortSignal,
380
- fetch: this.config.fetch
381
- });
382
- let durationInSeconds = 0;
383
- const segments = [];
384
- for (const monologue of transcriptionResult.monologues ?? []) {
385
- let currentSegmentText = "";
386
- let segmentStartSecond = 0;
387
- let hasStartedSegment = false;
388
- for (const element of monologue?.elements ?? []) {
389
- currentSegmentText += element.value;
390
- if (element.type === "text") {
391
- if (element.end_ts && element.end_ts > durationInSeconds) {
392
- durationInSeconds = element.end_ts;
393
- }
394
- if (!hasStartedSegment && typeof element.ts === "number") {
395
- segmentStartSecond = element.ts;
396
- hasStartedSegment = true;
397
- }
398
- if (typeof element.end_ts === "number" && hasStartedSegment) {
399
- if (currentSegmentText.trim()) {
400
- segments.push({
401
- text: currentSegmentText.trim(),
402
- startSecond: segmentStartSecond,
403
- endSecond: element.end_ts
404
- });
405
- }
406
- currentSegmentText = "";
407
- hasStartedSegment = false;
408
- }
409
- }
410
- }
411
- if (hasStartedSegment && currentSegmentText.trim()) {
412
- const endSecond = durationInSeconds > segmentStartSecond ? durationInSeconds : segmentStartSecond + 1;
413
- segments.push({
414
- text: currentSegmentText.trim(),
415
- startSecond: segmentStartSecond,
416
- endSecond
417
- });
418
- }
419
- }
420
- return {
421
- text: transcriptionResult.monologues?.map(
422
- (monologue) => monologue?.elements?.map((element) => element.value).join("")
423
- ).join(" ") ?? "",
424
- segments,
425
- language: submissionResponse.language ?? void 0,
426
- durationInSeconds,
427
- warnings,
428
- response: {
429
- timestamp: currentDate,
430
- modelId: this.modelId,
431
- headers: responseHeaders,
432
- body: rawResponse
433
- }
434
- };
435
- }
179
+ //#endregion
180
+ //#region src/revai-transcription-model.ts
181
+ var RevaiTranscriptionModel = class RevaiTranscriptionModel {
182
+ get provider() {
183
+ return this.config.provider;
184
+ }
185
+ static [WORKFLOW_SERIALIZE](model) {
186
+ return serializeModelOptions({
187
+ modelId: model.modelId,
188
+ config: model.config
189
+ });
190
+ }
191
+ static [WORKFLOW_DESERIALIZE](options) {
192
+ return new RevaiTranscriptionModel(options.modelId, options.config);
193
+ }
194
+ constructor(modelId, config) {
195
+ this.modelId = modelId;
196
+ this.config = config;
197
+ this.specificationVersion = "v4";
198
+ }
199
+ async getArgs({ audio, mediaType, providerOptions }) {
200
+ const warnings = [];
201
+ const revaiOptions = await parseProviderOptions({
202
+ provider: "revai",
203
+ providerOptions,
204
+ schema: revaiTranscriptionModelOptionsSchema
205
+ });
206
+ const formData = new FormData();
207
+ const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array(audio)]);
208
+ const fileExtension = mediaTypeToExtension(mediaType);
209
+ formData.append("media", new File([blob], "audio", { type: mediaType }), `audio.${fileExtension}`);
210
+ const transcriptionModelOptions = { transcriber: this.modelId };
211
+ if (revaiOptions) {
212
+ const formDataConfig = {
213
+ metadata: revaiOptions.metadata ?? void 0,
214
+ notification_config: revaiOptions.notification_config ?? void 0,
215
+ delete_after_seconds: revaiOptions.delete_after_seconds ?? void 0,
216
+ verbatim: revaiOptions.verbatim ?? void 0,
217
+ rush: revaiOptions.rush ?? void 0,
218
+ test_mode: revaiOptions.test_mode ?? void 0,
219
+ segments_to_transcribe: revaiOptions.segments_to_transcribe ?? void 0,
220
+ speaker_names: revaiOptions.speaker_names ?? void 0,
221
+ skip_diarization: revaiOptions.skip_diarization ?? void 0,
222
+ skip_postprocessing: revaiOptions.skip_postprocessing ?? void 0,
223
+ skip_punctuation: revaiOptions.skip_punctuation ?? void 0,
224
+ remove_disfluencies: revaiOptions.remove_disfluencies ?? void 0,
225
+ remove_atmospherics: revaiOptions.remove_atmospherics ?? void 0,
226
+ filter_profanity: revaiOptions.filter_profanity ?? void 0,
227
+ speaker_channels_count: revaiOptions.speaker_channels_count ?? void 0,
228
+ speakers_count: revaiOptions.speakers_count ?? void 0,
229
+ diarization_type: revaiOptions.diarization_type ?? void 0,
230
+ custom_vocabulary_id: revaiOptions.custom_vocabulary_id ?? void 0,
231
+ custom_vocabularies: revaiOptions.custom_vocabularies ?? void 0,
232
+ strict_custom_vocabulary: revaiOptions.strict_custom_vocabulary ?? void 0,
233
+ summarization_config: revaiOptions.summarization_config ?? void 0,
234
+ translation_config: revaiOptions.translation_config ?? void 0,
235
+ language: revaiOptions.language ?? void 0,
236
+ forced_alignment: revaiOptions.forced_alignment ?? void 0
237
+ };
238
+ for (const key in formDataConfig) {
239
+ const value = formDataConfig[key];
240
+ if (value !== void 0) transcriptionModelOptions[key] = value;
241
+ }
242
+ }
243
+ formData.append("config", JSON.stringify(transcriptionModelOptions));
244
+ return {
245
+ formData,
246
+ warnings
247
+ };
248
+ }
249
+ async doGenerate(options) {
250
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
251
+ const { formData, warnings } = await this.getArgs(options);
252
+ const { value: submissionResponse } = await postFormDataToApi({
253
+ url: this.config.url({
254
+ path: "/speechtotext/v1/jobs",
255
+ modelId: this.modelId
256
+ }),
257
+ headers: combineHeaders(this.config.headers?.(), options.headers),
258
+ formData,
259
+ failedResponseHandler: revaiFailedResponseHandler,
260
+ successfulResponseHandler: createJsonResponseHandler(revaiTranscriptionJobResponseSchema),
261
+ abortSignal: options.abortSignal,
262
+ fetch: this.config.fetch
263
+ });
264
+ if (submissionResponse.status === "failed") throw new AISDKError({
265
+ message: "Failed to submit transcription job to Rev.ai",
266
+ name: "TranscriptionJobSubmissionFailed",
267
+ cause: submissionResponse
268
+ });
269
+ const jobId = submissionResponse.id;
270
+ const timeoutMs = 6e4;
271
+ const startTime = Date.now();
272
+ const pollingInterval = 1e3;
273
+ let jobResponse = submissionResponse;
274
+ while (jobResponse.status !== "transcribed") {
275
+ if (Date.now() - startTime > timeoutMs) throw new AISDKError({
276
+ message: "Transcription job polling timed out",
277
+ name: "TranscriptionJobPollingTimedOut",
278
+ cause: submissionResponse
279
+ });
280
+ jobResponse = (await getFromApi({
281
+ url: this.config.url({
282
+ path: `/speechtotext/v1/jobs/${jobId}`,
283
+ modelId: this.modelId
284
+ }),
285
+ validateUrl: false,
286
+ headers: combineHeaders(this.config.headers?.(), options.headers),
287
+ failedResponseHandler: revaiFailedResponseHandler,
288
+ successfulResponseHandler: createJsonResponseHandler(revaiTranscriptionJobResponseSchema),
289
+ abortSignal: options.abortSignal,
290
+ fetch: this.config.fetch
291
+ })).value;
292
+ if (jobResponse.status === "failed") throw new AISDKError({
293
+ message: "Transcription job failed",
294
+ name: "TranscriptionJobFailed",
295
+ cause: jobResponse
296
+ });
297
+ if (jobResponse.status !== "transcribed") await delay(pollingInterval);
298
+ }
299
+ const { value: transcriptionResult, responseHeaders, rawValue: rawResponse } = await getFromApi({
300
+ url: this.config.url({
301
+ path: `/speechtotext/v1/jobs/${jobId}/transcript`,
302
+ modelId: this.modelId
303
+ }),
304
+ validateUrl: false,
305
+ headers: combineHeaders(this.config.headers?.(), options.headers),
306
+ failedResponseHandler: revaiFailedResponseHandler,
307
+ successfulResponseHandler: createJsonResponseHandler(revaiTranscriptionResponseSchema),
308
+ abortSignal: options.abortSignal,
309
+ fetch: this.config.fetch
310
+ });
311
+ let durationInSeconds = 0;
312
+ const segments = [];
313
+ for (const monologue of transcriptionResult.monologues ?? []) {
314
+ let currentSegmentText = "";
315
+ let segmentStartSecond = 0;
316
+ let hasStartedSegment = false;
317
+ for (const element of monologue?.elements ?? []) {
318
+ currentSegmentText += element.value;
319
+ if (element.type === "text") {
320
+ if (element.end_ts && element.end_ts > durationInSeconds) durationInSeconds = element.end_ts;
321
+ if (!hasStartedSegment && typeof element.ts === "number") {
322
+ segmentStartSecond = element.ts;
323
+ hasStartedSegment = true;
324
+ }
325
+ if (typeof element.end_ts === "number" && hasStartedSegment) {
326
+ if (currentSegmentText.trim()) segments.push({
327
+ text: currentSegmentText.trim(),
328
+ startSecond: segmentStartSecond,
329
+ endSecond: element.end_ts
330
+ });
331
+ currentSegmentText = "";
332
+ hasStartedSegment = false;
333
+ }
334
+ }
335
+ }
336
+ if (hasStartedSegment && currentSegmentText.trim()) {
337
+ const endSecond = durationInSeconds > segmentStartSecond ? durationInSeconds : segmentStartSecond + 1;
338
+ segments.push({
339
+ text: currentSegmentText.trim(),
340
+ startSecond: segmentStartSecond,
341
+ endSecond
342
+ });
343
+ }
344
+ }
345
+ return {
346
+ text: transcriptionResult.monologues?.map((monologue) => monologue?.elements?.map((element) => element.value).join("")).join(" ") ?? "",
347
+ segments,
348
+ language: submissionResponse.language ?? void 0,
349
+ durationInSeconds,
350
+ warnings,
351
+ response: {
352
+ timestamp: currentDate,
353
+ modelId: this.modelId,
354
+ headers: responseHeaders,
355
+ body: rawResponse
356
+ }
357
+ };
358
+ }
436
359
  };
437
- var revaiTranscriptionJobResponseSchema = z3.object({
438
- id: z3.string().nullish(),
439
- status: z3.string().nullish(),
440
- language: z3.string().nullish()
360
+ const revaiTranscriptionJobResponseSchema = z.object({
361
+ id: z.string().nullish(),
362
+ status: z.string().nullish(),
363
+ language: z.string().nullish()
441
364
  });
442
- var revaiTranscriptionResponseSchema = z3.object({
443
- monologues: z3.array(
444
- z3.object({
445
- elements: z3.array(
446
- z3.object({
447
- type: z3.string().nullish(),
448
- value: z3.string().nullish(),
449
- ts: z3.number().nullish(),
450
- end_ts: z3.number().nullish()
451
- })
452
- ).nullish()
453
- })
454
- ).nullish()
455
- });
456
-
457
- // src/version.ts
458
- var VERSION = true ? "3.0.51" : "0.0.0-test";
459
-
460
- // src/revai-provider.ts
365
+ const revaiTranscriptionResponseSchema = z.object({ monologues: z.array(z.object({ elements: z.array(z.object({
366
+ type: z.string().nullish(),
367
+ value: z.string().nullish(),
368
+ ts: z.number().nullish(),
369
+ end_ts: z.number().nullish()
370
+ })).nullish() })).nullish() });
371
+ //#endregion
372
+ //#region src/version.ts
373
+ const VERSION = "3.0.52";
374
+ //#endregion
375
+ //#region src/revai-provider.ts
376
+ /**
377
+ * Create a Rev.ai provider instance.
378
+ */
461
379
  function createRevai(options = {}) {
462
- const getHeaders = () => withUserAgentSuffix(
463
- {
464
- authorization: `Bearer ${loadApiKey({
465
- apiKey: options.apiKey,
466
- environmentVariableName: "REVAI_API_KEY",
467
- description: "Rev.ai"
468
- })}`,
469
- ...options.headers
470
- },
471
- `ai-sdk-revai/${VERSION}`
472
- );
473
- const createTranscriptionModel = (modelId) => new RevaiTranscriptionModel(modelId, {
474
- provider: `revai.transcription`,
475
- url: ({ path }) => `https://api.rev.ai${path}`,
476
- headers: getHeaders,
477
- fetch: options.fetch
478
- });
479
- const provider = function(modelId) {
480
- return {
481
- transcription: createTranscriptionModel(modelId)
482
- };
483
- };
484
- provider.specificationVersion = "v4";
485
- provider.transcription = createTranscriptionModel;
486
- provider.transcriptionModel = createTranscriptionModel;
487
- provider.languageModel = () => {
488
- throw new NoSuchModelError({
489
- modelId: "unknown",
490
- modelType: "languageModel",
491
- message: "Rev.ai does not provide language models"
492
- });
493
- };
494
- provider.embeddingModel = () => {
495
- throw new NoSuchModelError({
496
- modelId: "unknown",
497
- modelType: "embeddingModel",
498
- message: "Rev.ai does not provide text embedding models"
499
- });
500
- };
501
- provider.textEmbeddingModel = provider.embeddingModel;
502
- provider.imageModel = () => {
503
- throw new NoSuchModelError({
504
- modelId: "unknown",
505
- modelType: "imageModel",
506
- message: "Rev.ai does not provide image models"
507
- });
508
- };
509
- return provider;
380
+ const getHeaders = () => withUserAgentSuffix({
381
+ authorization: `Bearer ${loadApiKey({
382
+ apiKey: options.apiKey,
383
+ environmentVariableName: "REVAI_API_KEY",
384
+ description: "Rev.ai"
385
+ })}`,
386
+ ...options.headers
387
+ }, `ai-sdk-revai/${VERSION}`);
388
+ const createTranscriptionModel = (modelId) => new RevaiTranscriptionModel(modelId, {
389
+ provider: `revai.transcription`,
390
+ url: ({ path }) => `https://api.rev.ai${path}`,
391
+ headers: getHeaders,
392
+ fetch: options.fetch
393
+ });
394
+ const provider = function(modelId) {
395
+ return { transcription: createTranscriptionModel(modelId) };
396
+ };
397
+ provider.specificationVersion = "v4";
398
+ provider.transcription = createTranscriptionModel;
399
+ provider.transcriptionModel = createTranscriptionModel;
400
+ provider.languageModel = () => {
401
+ throw new NoSuchModelError({
402
+ modelId: "unknown",
403
+ modelType: "languageModel",
404
+ message: "Rev.ai does not provide language models"
405
+ });
406
+ };
407
+ provider.embeddingModel = () => {
408
+ throw new NoSuchModelError({
409
+ modelId: "unknown",
410
+ modelType: "embeddingModel",
411
+ message: "Rev.ai does not provide text embedding models"
412
+ });
413
+ };
414
+ provider.textEmbeddingModel = provider.embeddingModel;
415
+ provider.imageModel = () => {
416
+ throw new NoSuchModelError({
417
+ modelId: "unknown",
418
+ modelType: "imageModel",
419
+ message: "Rev.ai does not provide image models"
420
+ });
421
+ };
422
+ return provider;
510
423
  }
511
- var revai = createRevai();
512
- export {
513
- VERSION,
514
- createRevai,
515
- revai
516
- };
424
+ /**
425
+ * Default Rev.ai provider instance.
426
+ */
427
+ const revai = createRevai();
428
+ //#endregion
429
+ export { VERSION, createRevai, revai };
430
+
517
431
  //# sourceMappingURL=index.js.map