voice-router-dev 0.1.0

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 ADDED
@@ -0,0 +1,4880 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.ts
32
+ var src_exports = {};
33
+ __export(src_exports, {
34
+ AssemblyAIAdapter: () => AssemblyAIAdapter,
35
+ AssemblyAITypes: () => schema_exports2,
36
+ AssemblyAIWebhookHandler: () => AssemblyAIWebhookHandler,
37
+ AzureSTTAdapter: () => AzureSTTAdapter,
38
+ AzureWebhookHandler: () => AzureWebhookHandler,
39
+ BaseAdapter: () => BaseAdapter,
40
+ BaseWebhookHandler: () => BaseWebhookHandler,
41
+ DeepgramAdapter: () => DeepgramAdapter,
42
+ DeepgramWebhookHandler: () => DeepgramWebhookHandler,
43
+ GladiaAdapter: () => GladiaAdapter,
44
+ GladiaTypes: () => schema_exports,
45
+ GladiaWebhookHandler: () => GladiaWebhookHandler,
46
+ OpenAIWhisperAdapter: () => OpenAIWhisperAdapter,
47
+ SpeechmaticsAdapter: () => SpeechmaticsAdapter,
48
+ SpeechmaticsWebhookHandler: () => SpeechmaticsWebhookHandler,
49
+ VoiceRouter: () => VoiceRouter,
50
+ WebhookRouter: () => WebhookRouter,
51
+ createAssemblyAIAdapter: () => createAssemblyAIAdapter,
52
+ createAssemblyAIWebhookHandler: () => createAssemblyAIWebhookHandler,
53
+ createAzureSTTAdapter: () => createAzureSTTAdapter,
54
+ createAzureWebhookHandler: () => createAzureWebhookHandler,
55
+ createDeepgramAdapter: () => createDeepgramAdapter,
56
+ createDeepgramWebhookHandler: () => createDeepgramWebhookHandler,
57
+ createGladiaAdapter: () => createGladiaAdapter,
58
+ createGladiaWebhookHandler: () => createGladiaWebhookHandler,
59
+ createOpenAIWhisperAdapter: () => createOpenAIWhisperAdapter,
60
+ createSpeechmaticsAdapter: () => createSpeechmaticsAdapter,
61
+ createVoiceRouter: () => createVoiceRouter,
62
+ createWebhookRouter: () => createWebhookRouter
63
+ });
64
+ module.exports = __toCommonJS(src_exports);
65
+
66
+ // src/router/voice-router.ts
67
+ var VoiceRouter = class {
68
+ constructor(config) {
69
+ this.adapters = /* @__PURE__ */ new Map();
70
+ this.roundRobinIndex = 0;
71
+ this.config = {
72
+ selectionStrategy: "default",
73
+ ...config
74
+ };
75
+ if (Object.keys(config.providers).length === 0) {
76
+ throw new Error("VoiceRouter requires at least one provider configuration");
77
+ }
78
+ if (this.config.selectionStrategy === "default" && !this.config.defaultProvider) {
79
+ this.config.defaultProvider = Object.keys(config.providers)[0];
80
+ }
81
+ }
82
+ /**
83
+ * Register an adapter for a provider
84
+ *
85
+ * Call this method for each provider you want to use. The adapter will be
86
+ * initialized with the configuration provided in the constructor.
87
+ *
88
+ * @param adapter - Provider adapter instance to register
89
+ * @throws {Error} If no configuration found for the provider
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * const router = new VoiceRouter({
94
+ * providers: {
95
+ * gladia: { apiKey: 'YOUR_KEY' }
96
+ * }
97
+ * });
98
+ *
99
+ * router.registerAdapter(new GladiaAdapter());
100
+ * ```
101
+ */
102
+ registerAdapter(adapter) {
103
+ const providerConfig = this.config.providers[adapter.name];
104
+ if (!providerConfig) {
105
+ throw new Error(`No configuration found for provider: ${adapter.name}`);
106
+ }
107
+ adapter.initialize(providerConfig);
108
+ this.adapters.set(adapter.name, adapter);
109
+ }
110
+ /**
111
+ * Get an adapter by provider name
112
+ */
113
+ getAdapter(provider) {
114
+ const adapter = this.adapters.get(provider);
115
+ if (!adapter) {
116
+ throw new Error(
117
+ `Provider '${provider}' is not registered. Available providers: ${Array.from(this.adapters.keys()).join(", ")}`
118
+ );
119
+ }
120
+ return adapter;
121
+ }
122
+ /**
123
+ * Select provider based on configured strategy
124
+ */
125
+ selectProvider(preferredProvider) {
126
+ if (preferredProvider) {
127
+ if (!this.adapters.has(preferredProvider)) {
128
+ throw new Error(
129
+ `Provider '${preferredProvider}' is not registered. Available providers: ${Array.from(this.adapters.keys()).join(", ")}`
130
+ );
131
+ }
132
+ return preferredProvider;
133
+ }
134
+ switch (this.config.selectionStrategy) {
135
+ case "explicit":
136
+ throw new Error(
137
+ "Provider must be explicitly specified when using 'explicit' selection strategy"
138
+ );
139
+ case "round-robin": {
140
+ const providers = Array.from(this.adapters.keys());
141
+ const provider = providers[this.roundRobinIndex % providers.length];
142
+ this.roundRobinIndex++;
143
+ return provider;
144
+ }
145
+ case "default":
146
+ default:
147
+ if (!this.config.defaultProvider) {
148
+ throw new Error("No default provider configured");
149
+ }
150
+ return this.config.defaultProvider;
151
+ }
152
+ }
153
+ /**
154
+ * Transcribe audio using a specific provider or the default
155
+ *
156
+ * Submit audio for transcription. The provider will be selected based on
157
+ * your configuration strategy (explicit, default, or round-robin).
158
+ *
159
+ * @param audio - Audio input (URL, file buffer, or stream)
160
+ * @param options - Transcription options (language, diarization, etc.)
161
+ * @param options.provider - Specific provider to use (overrides selection strategy)
162
+ * @returns Unified transcription response with normalized format
163
+ * @throws {Error} If provider not registered or selection fails
164
+ *
165
+ * @example URL audio
166
+ * ```typescript
167
+ * const result = await router.transcribe({
168
+ * type: 'url',
169
+ * url: 'https://example.com/audio.mp3'
170
+ * }, {
171
+ * language: 'en',
172
+ * diarization: true,
173
+ * summarization: true
174
+ * });
175
+ *
176
+ * if (result.success) {
177
+ * console.log('Transcript:', result.data.text);
178
+ * console.log('Speakers:', result.data.speakers);
179
+ * console.log('Summary:', result.data.summary);
180
+ * }
181
+ * ```
182
+ *
183
+ * @example Specific provider
184
+ * ```typescript
185
+ * const result = await router.transcribe(audio, {
186
+ * provider: 'gladia', // Force use of Gladia
187
+ * language: 'en'
188
+ * });
189
+ * ```
190
+ */
191
+ async transcribe(audio, options) {
192
+ const provider = this.selectProvider(options?.provider);
193
+ const adapter = this.getAdapter(provider);
194
+ const { provider: _, ...adapterOptions } = options || {};
195
+ return adapter.transcribe(audio, adapterOptions);
196
+ }
197
+ /**
198
+ * Get transcription result by ID
199
+ * Provider must be specified since IDs are provider-specific
200
+ */
201
+ async getTranscript(transcriptId, provider) {
202
+ const adapter = this.getAdapter(provider);
203
+ return adapter.getTranscript(transcriptId);
204
+ }
205
+ /**
206
+ * Stream audio for real-time transcription
207
+ * Only works with providers that support streaming
208
+ *
209
+ * @param options - Streaming options including provider selection
210
+ * @param callbacks - Event callbacks for transcription results
211
+ * @returns Promise that resolves with a StreamingSession
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * import { VoiceRouter } from '@meeting-baas/sdk';
216
+ *
217
+ * const router = new VoiceRouter();
218
+ * router.initialize({
219
+ * gladia: { apiKey: process.env.GLADIA_KEY },
220
+ * deepgram: { apiKey: process.env.DEEPGRAM_KEY }
221
+ * });
222
+ *
223
+ * const session = await router.transcribeStream({
224
+ * provider: 'deepgram',
225
+ * encoding: 'linear16',
226
+ * sampleRate: 16000,
227
+ * language: 'en'
228
+ * }, {
229
+ * onTranscript: (event) => console.log(event.text),
230
+ * onError: (error) => console.error(error)
231
+ * });
232
+ *
233
+ * // Send audio chunks
234
+ * await session.sendAudio({ data: audioBuffer });
235
+ * await session.close();
236
+ * ```
237
+ */
238
+ async transcribeStream(options, callbacks) {
239
+ const provider = this.selectProvider(options?.provider);
240
+ const adapter = this.getAdapter(provider);
241
+ if (!adapter.capabilities.streaming || !adapter.transcribeStream) {
242
+ throw new Error(`Provider '${provider}' does not support streaming transcription`);
243
+ }
244
+ const { provider: _, ...adapterOptions } = options || {};
245
+ return adapter.transcribeStream(adapterOptions, callbacks);
246
+ }
247
+ /**
248
+ * Delete a transcription
249
+ * Not all providers support this operation
250
+ */
251
+ async deleteTranscript(transcriptId, provider) {
252
+ const adapter = this.getAdapter(provider);
253
+ if (!adapter.deleteTranscript) {
254
+ throw new Error(`Provider '${provider}' does not support deleting transcripts`);
255
+ }
256
+ return adapter.deleteTranscript(transcriptId);
257
+ }
258
+ /**
259
+ * List recent transcriptions
260
+ * Not all providers support this operation
261
+ */
262
+ async listTranscripts(provider, options) {
263
+ const adapter = this.getAdapter(provider);
264
+ if (!adapter.listTranscripts) {
265
+ throw new Error(`Provider '${provider}' does not support listing transcripts`);
266
+ }
267
+ return adapter.listTranscripts(options);
268
+ }
269
+ /**
270
+ * Get capabilities for a specific provider
271
+ */
272
+ getProviderCapabilities(provider) {
273
+ const adapter = this.getAdapter(provider);
274
+ return adapter.capabilities;
275
+ }
276
+ /**
277
+ * Get all registered providers
278
+ */
279
+ getRegisteredProviders() {
280
+ return Array.from(this.adapters.keys());
281
+ }
282
+ /**
283
+ * Get raw provider client for advanced usage
284
+ */
285
+ getRawProviderClient(provider) {
286
+ const adapter = this.getAdapter(provider);
287
+ if (!adapter.getRawClient) {
288
+ throw new Error(`Provider '${provider}' does not expose a raw client`);
289
+ }
290
+ return adapter.getRawClient();
291
+ }
292
+ };
293
+ function createVoiceRouter(config, adapters) {
294
+ const router = new VoiceRouter(config);
295
+ if (adapters && adapters.length > 0) {
296
+ for (const adapter of adapters) {
297
+ router.registerAdapter(adapter);
298
+ }
299
+ }
300
+ return router;
301
+ }
302
+
303
+ // src/adapters/base-adapter.ts
304
+ var BaseAdapter = class {
305
+ initialize(config) {
306
+ this.config = config;
307
+ }
308
+ /**
309
+ * Helper method to create error responses
310
+ */
311
+ createErrorResponse(error, statusCode) {
312
+ const err = error;
313
+ return {
314
+ success: false,
315
+ provider: this.name,
316
+ error: {
317
+ code: err.code || "UNKNOWN_ERROR",
318
+ message: err.message || "An unknown error occurred",
319
+ statusCode: statusCode || err.statusCode,
320
+ details: error
321
+ }
322
+ };
323
+ }
324
+ /**
325
+ * Helper method to validate configuration
326
+ */
327
+ validateConfig() {
328
+ if (!this.config) {
329
+ throw new Error(`Adapter ${this.name} is not initialized. Call initialize() first.`);
330
+ }
331
+ if (!this.config.apiKey) {
332
+ throw new Error(`API key is required for ${this.name} provider`);
333
+ }
334
+ }
335
+ };
336
+
337
+ // src/adapters/gladia-adapter.ts
338
+ var import_axios = __toESM(require("axios"));
339
+ var import_ws = __toESM(require("ws"));
340
+ var GladiaAdapter = class extends BaseAdapter {
341
+ constructor() {
342
+ super(...arguments);
343
+ this.name = "gladia";
344
+ this.capabilities = {
345
+ streaming: true,
346
+ diarization: true,
347
+ wordTimestamps: true,
348
+ languageDetection: true,
349
+ customVocabulary: true,
350
+ summarization: true,
351
+ sentimentAnalysis: true,
352
+ entityDetection: true,
353
+ piiRedaction: false
354
+ // Gladia doesn't have PII redaction in their API
355
+ };
356
+ this.baseUrl = "https://api.gladia.io/v2";
357
+ }
358
+ initialize(config) {
359
+ super.initialize(config);
360
+ this.client = import_axios.default.create({
361
+ baseURL: config.baseUrl || this.baseUrl,
362
+ timeout: config.timeout || 6e4,
363
+ headers: {
364
+ "x-gladia-key": config.apiKey,
365
+ "Content-Type": "application/json",
366
+ ...config.headers
367
+ }
368
+ });
369
+ }
370
+ /**
371
+ * Submit audio for transcription
372
+ *
373
+ * Sends audio to Gladia API for transcription. If a webhook URL is provided,
374
+ * returns immediately with the job ID. Otherwise, polls until completion.
375
+ *
376
+ * @param audio - Audio input (currently only URL type supported)
377
+ * @param options - Transcription options
378
+ * @param options.language - Language code (e.g., 'en', 'es', 'fr')
379
+ * @param options.languageDetection - Enable automatic language detection
380
+ * @param options.diarization - Enable speaker identification
381
+ * @param options.speakersExpected - Number of expected speakers (for diarization)
382
+ * @param options.summarization - Generate text summary
383
+ * @param options.sentimentAnalysis - Analyze sentiment of transcription
384
+ * @param options.customVocabulary - Words to boost in recognition
385
+ * @param options.webhookUrl - Callback URL for async results
386
+ * @returns Normalized transcription response
387
+ * @throws {Error} If audio type is not 'url' (file/stream not yet supported)
388
+ *
389
+ * @example Simple transcription
390
+ * ```typescript
391
+ * const result = await adapter.transcribe({
392
+ * type: 'url',
393
+ * url: 'https://example.com/meeting.mp3'
394
+ * });
395
+ * ```
396
+ *
397
+ * @example With advanced features
398
+ * ```typescript
399
+ * const result = await adapter.transcribe({
400
+ * type: 'url',
401
+ * url: 'https://example.com/meeting.mp3'
402
+ * }, {
403
+ * language: 'en',
404
+ * diarization: true,
405
+ * speakersExpected: 3,
406
+ * summarization: true,
407
+ * customVocabulary: ['API', 'TypeScript', 'JavaScript']
408
+ * });
409
+ * ```
410
+ *
411
+ * @example With webhook (returns job ID immediately for polling)
412
+ * ```typescript
413
+ * // Submit transcription with webhook
414
+ * const result = await adapter.transcribe({
415
+ * type: 'url',
416
+ * url: 'https://example.com/meeting.mp3'
417
+ * }, {
418
+ * webhookUrl: 'https://myapp.com/webhook/transcription',
419
+ * language: 'en'
420
+ * });
421
+ *
422
+ * // Get job ID for polling
423
+ * const jobId = result.data?.id;
424
+ * console.log('Job ID:', jobId); // Use this to poll for status
425
+ *
426
+ * // Later: Poll for completion (if webhook fails or you want to check)
427
+ * const status = await adapter.getTranscript(jobId);
428
+ * if (status.data?.status === 'completed') {
429
+ * console.log('Transcript:', status.data.text);
430
+ * }
431
+ * ```
432
+ */
433
+ async transcribe(audio, options) {
434
+ this.validateConfig();
435
+ try {
436
+ const payload = this.buildTranscriptionRequest(audio, options);
437
+ const response = await this.client.post(
438
+ "/transcription",
439
+ payload
440
+ );
441
+ const jobId = response.data.id;
442
+ if (options?.webhookUrl) {
443
+ return {
444
+ success: true,
445
+ provider: this.name,
446
+ data: {
447
+ id: jobId,
448
+ text: "",
449
+ status: "queued"
450
+ },
451
+ raw: response.data
452
+ };
453
+ }
454
+ return await this.pollForCompletion(jobId);
455
+ } catch (error) {
456
+ return this.createErrorResponse(error);
457
+ }
458
+ }
459
+ /**
460
+ * Get transcription result by ID
461
+ */
462
+ async getTranscript(transcriptId) {
463
+ this.validateConfig();
464
+ try {
465
+ const response = await this.client.get(`/transcription/${transcriptId}`);
466
+ return this.normalizeResponse(response.data);
467
+ } catch (error) {
468
+ return this.createErrorResponse(error);
469
+ }
470
+ }
471
+ /**
472
+ * Build Gladia transcription request from unified options
473
+ */
474
+ buildTranscriptionRequest(audio, options) {
475
+ let audioUrl;
476
+ if (audio.type === "url") {
477
+ audioUrl = audio.url;
478
+ } else {
479
+ throw new Error(
480
+ "Gladia adapter currently only supports URL-based audio input. Use audio.type='url'"
481
+ );
482
+ }
483
+ const request = {
484
+ audio_url: audioUrl
485
+ };
486
+ if (options) {
487
+ if (options.language || options.languageDetection) {
488
+ request.language_config = {
489
+ languages: options.language ? [options.language] : void 0,
490
+ code_switching: options.languageDetection
491
+ };
492
+ }
493
+ if (options.diarization) {
494
+ request.diarization = true;
495
+ if (options.speakersExpected) {
496
+ request.diarization_config = {
497
+ number_of_speakers: options.speakersExpected
498
+ };
499
+ }
500
+ }
501
+ if (options.customVocabulary && options.customVocabulary.length > 0) {
502
+ request.custom_vocabulary = true;
503
+ request.custom_vocabulary_config = {
504
+ vocabulary: options.customVocabulary
505
+ };
506
+ }
507
+ if (options.summarization) {
508
+ request.summarization = true;
509
+ }
510
+ if (options.sentimentAnalysis) {
511
+ request.sentiment_analysis = true;
512
+ }
513
+ if (options.entityDetection) {
514
+ request.named_entity_recognition = true;
515
+ }
516
+ if (options.webhookUrl) {
517
+ request.callback = true;
518
+ request.callback_config = {
519
+ url: options.webhookUrl
520
+ };
521
+ }
522
+ if (options.metadata) {
523
+ request.custom_metadata = options.metadata;
524
+ }
525
+ }
526
+ return request;
527
+ }
528
+ /**
529
+ * Normalize Gladia response to unified format
530
+ */
531
+ normalizeResponse(response) {
532
+ let status;
533
+ switch (response.status) {
534
+ case "queued":
535
+ status = "queued";
536
+ break;
537
+ case "processing":
538
+ status = "processing";
539
+ break;
540
+ case "done":
541
+ status = "completed";
542
+ break;
543
+ case "error":
544
+ status = "error";
545
+ break;
546
+ default:
547
+ status = "queued";
548
+ }
549
+ if (response.status === "error") {
550
+ return {
551
+ success: false,
552
+ provider: this.name,
553
+ error: {
554
+ code: response.error_code?.toString() || "TRANSCRIPTION_ERROR",
555
+ message: "Transcription failed",
556
+ statusCode: response.error_code || void 0
557
+ },
558
+ raw: response
559
+ };
560
+ }
561
+ const result = response.result;
562
+ const transcription = result?.transcription;
563
+ return {
564
+ success: true,
565
+ provider: this.name,
566
+ data: {
567
+ id: response.id,
568
+ text: transcription?.full_transcript || "",
569
+ confidence: void 0,
570
+ // Gladia doesn't provide overall confidence
571
+ status,
572
+ language: transcription?.languages?.[0],
573
+ // Use first detected language
574
+ duration: void 0,
575
+ // Not directly available in Gladia response
576
+ speakers: this.extractSpeakers(transcription),
577
+ words: this.extractWords(transcription),
578
+ utterances: this.extractUtterances(transcription),
579
+ summary: result?.summarization?.results || void 0,
580
+ metadata: {
581
+ requestParams: response.request_params,
582
+ customMetadata: response.custom_metadata
583
+ },
584
+ createdAt: response.created_at,
585
+ completedAt: response.completed_at || void 0
586
+ },
587
+ raw: response
588
+ };
589
+ }
590
+ /**
591
+ * Extract speaker information from Gladia response
592
+ */
593
+ extractSpeakers(transcription) {
594
+ if (!transcription?.utterances) {
595
+ return void 0;
596
+ }
597
+ const speakerSet = /* @__PURE__ */ new Set();
598
+ transcription.utterances.forEach((utterance) => {
599
+ if (utterance.speaker !== void 0) {
600
+ speakerSet.add(utterance.speaker);
601
+ }
602
+ });
603
+ if (speakerSet.size === 0) {
604
+ return void 0;
605
+ }
606
+ return Array.from(speakerSet).map((speakerId) => ({
607
+ id: speakerId.toString(),
608
+ label: `Speaker ${speakerId}`
609
+ }));
610
+ }
611
+ /**
612
+ * Extract word timestamps from Gladia response
613
+ */
614
+ extractWords(transcription) {
615
+ if (!transcription?.utterances) {
616
+ return void 0;
617
+ }
618
+ const allWords = transcription.utterances.flatMap(
619
+ (utterance) => utterance.words.map((word) => ({
620
+ text: word.word,
621
+ start: word.start,
622
+ end: word.end,
623
+ confidence: word.confidence,
624
+ speaker: utterance.speaker?.toString()
625
+ }))
626
+ );
627
+ return allWords.length > 0 ? allWords : void 0;
628
+ }
629
+ /**
630
+ * Extract utterances from Gladia response
631
+ */
632
+ extractUtterances(transcription) {
633
+ if (!transcription?.utterances) {
634
+ return void 0;
635
+ }
636
+ return transcription.utterances.map((utterance) => ({
637
+ text: utterance.text,
638
+ start: utterance.start,
639
+ end: utterance.end,
640
+ speaker: utterance.speaker?.toString(),
641
+ confidence: utterance.confidence,
642
+ words: utterance.words.map((word) => ({
643
+ text: word.word,
644
+ start: word.start,
645
+ end: word.end,
646
+ confidence: word.confidence
647
+ }))
648
+ }));
649
+ }
650
+ /**
651
+ * Poll for transcription completion
652
+ */
653
+ async pollForCompletion(jobId, maxAttempts = 60, intervalMs = 2e3) {
654
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
655
+ const result = await this.getTranscript(jobId);
656
+ if (!result.success) {
657
+ return result;
658
+ }
659
+ const status = result.data?.status;
660
+ if (status === "completed") {
661
+ return result;
662
+ }
663
+ if (status === "error") {
664
+ return {
665
+ success: false,
666
+ provider: this.name,
667
+ error: {
668
+ code: "TRANSCRIPTION_ERROR",
669
+ message: "Transcription failed"
670
+ },
671
+ raw: result.raw
672
+ };
673
+ }
674
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
675
+ }
676
+ return {
677
+ success: false,
678
+ provider: this.name,
679
+ error: {
680
+ code: "POLLING_TIMEOUT",
681
+ message: `Transcription did not complete after ${maxAttempts} attempts`
682
+ }
683
+ };
684
+ }
685
+ /**
686
+ * Stream audio for real-time transcription
687
+ *
688
+ * Creates a WebSocket connection to Gladia for streaming transcription.
689
+ * First initializes a session via REST API, then connects to WebSocket.
690
+ *
691
+ * @param options - Streaming configuration options
692
+ * @param callbacks - Event callbacks for transcription results
693
+ * @returns Promise that resolves with a StreamingSession
694
+ *
695
+ * @example Real-time streaming
696
+ * ```typescript
697
+ * const session = await adapter.transcribeStream({
698
+ * encoding: 'wav/pcm',
699
+ * sampleRate: 16000,
700
+ * channels: 1,
701
+ * language: 'en',
702
+ * interimResults: true
703
+ * }, {
704
+ * onOpen: () => console.log('Connected'),
705
+ * onTranscript: (event) => {
706
+ * if (event.isFinal) {
707
+ * console.log('Final:', event.text);
708
+ * } else {
709
+ * console.log('Interim:', event.text);
710
+ * }
711
+ * },
712
+ * onError: (error) => console.error('Error:', error),
713
+ * onClose: () => console.log('Disconnected')
714
+ * });
715
+ *
716
+ * // Send audio chunks
717
+ * const audioChunk = getAudioChunk(); // Your audio source
718
+ * await session.sendAudio({ data: audioChunk });
719
+ *
720
+ * // Close when done
721
+ * await session.close();
722
+ * ```
723
+ */
724
+ async transcribeStream(options, callbacks) {
725
+ this.validateConfig();
726
+ const streamingRequest = {
727
+ encoding: options?.encoding,
728
+ sample_rate: options?.sampleRate,
729
+ channels: options?.channels,
730
+ endpointing: options?.endpointing
731
+ };
732
+ if (options?.language) {
733
+ streamingRequest.language_config = {
734
+ languages: [options.language]
735
+ };
736
+ }
737
+ const initResponse = await this.client.post(
738
+ "/streaming/init",
739
+ streamingRequest
740
+ );
741
+ const { id, url: wsUrl } = initResponse.data;
742
+ const ws = new import_ws.default(wsUrl);
743
+ let sessionStatus = "connecting";
744
+ ws.on("open", () => {
745
+ sessionStatus = "open";
746
+ callbacks?.onOpen?.();
747
+ });
748
+ ws.on("message", (data) => {
749
+ try {
750
+ const message = JSON.parse(data.toString());
751
+ if (message.type === "transcript") {
752
+ callbacks?.onTranscript?.({
753
+ type: "transcript",
754
+ text: message.text || "",
755
+ isFinal: message.is_final === true,
756
+ confidence: message.confidence,
757
+ words: message.words?.map((word) => ({
758
+ text: word.word || word.text,
759
+ start: word.start,
760
+ end: word.end,
761
+ confidence: word.confidence
762
+ })),
763
+ data: message
764
+ });
765
+ } else if (message.type === "utterance") {
766
+ const utterance = {
767
+ text: message.text || "",
768
+ start: message.start || 0,
769
+ end: message.end || 0,
770
+ speaker: message.speaker?.toString(),
771
+ confidence: message.confidence,
772
+ words: message.words?.map((word) => ({
773
+ text: word.word || word.text,
774
+ start: word.start,
775
+ end: word.end,
776
+ confidence: word.confidence
777
+ }))
778
+ };
779
+ callbacks?.onUtterance?.(utterance);
780
+ } else if (message.type === "metadata") {
781
+ callbacks?.onMetadata?.(message);
782
+ }
783
+ } catch (error) {
784
+ callbacks?.onError?.({
785
+ code: "PARSE_ERROR",
786
+ message: "Failed to parse WebSocket message",
787
+ details: error
788
+ });
789
+ }
790
+ });
791
+ ws.on("error", (error) => {
792
+ callbacks?.onError?.({
793
+ code: "WEBSOCKET_ERROR",
794
+ message: error.message,
795
+ details: error
796
+ });
797
+ });
798
+ ws.on("close", (code, reason) => {
799
+ sessionStatus = "closed";
800
+ callbacks?.onClose?.(code, reason.toString());
801
+ });
802
+ await new Promise((resolve, reject) => {
803
+ const timeout = setTimeout(() => {
804
+ reject(new Error("WebSocket connection timeout"));
805
+ }, 1e4);
806
+ ws.once("open", () => {
807
+ clearTimeout(timeout);
808
+ resolve();
809
+ });
810
+ ws.once("error", (error) => {
811
+ clearTimeout(timeout);
812
+ reject(error);
813
+ });
814
+ });
815
+ return {
816
+ id,
817
+ provider: this.name,
818
+ createdAt: /* @__PURE__ */ new Date(),
819
+ getStatus: () => sessionStatus,
820
+ sendAudio: async (chunk) => {
821
+ if (sessionStatus !== "open") {
822
+ throw new Error(`Cannot send audio: session is ${sessionStatus}`);
823
+ }
824
+ if (ws.readyState !== import_ws.default.OPEN) {
825
+ throw new Error("WebSocket is not open");
826
+ }
827
+ ws.send(chunk.data);
828
+ if (chunk.isLast) {
829
+ ws.send(
830
+ JSON.stringify({
831
+ type: "stop_recording"
832
+ })
833
+ );
834
+ }
835
+ },
836
+ close: async () => {
837
+ if (sessionStatus === "closed" || sessionStatus === "closing") {
838
+ return;
839
+ }
840
+ sessionStatus = "closing";
841
+ if (ws.readyState === import_ws.default.OPEN) {
842
+ ws.send(
843
+ JSON.stringify({
844
+ type: "stop_recording"
845
+ })
846
+ );
847
+ }
848
+ return new Promise((resolve) => {
849
+ const timeout = setTimeout(() => {
850
+ ws.terminate();
851
+ resolve();
852
+ }, 5e3);
853
+ ws.close();
854
+ ws.once("close", () => {
855
+ clearTimeout(timeout);
856
+ sessionStatus = "closed";
857
+ resolve();
858
+ });
859
+ });
860
+ }
861
+ };
862
+ }
863
+ };
864
+ function createGladiaAdapter(config) {
865
+ const adapter = new GladiaAdapter();
866
+ adapter.initialize(config);
867
+ return adapter;
868
+ }
869
+
870
+ // src/adapters/assemblyai-adapter.ts
871
+ var import_axios2 = __toESM(require("axios"));
872
+ var import_ws2 = __toESM(require("ws"));
873
+ var AssemblyAIAdapter = class extends BaseAdapter {
874
+ constructor() {
875
+ super(...arguments);
876
+ this.name = "assemblyai";
877
+ this.capabilities = {
878
+ streaming: true,
879
+ diarization: true,
880
+ wordTimestamps: true,
881
+ languageDetection: true,
882
+ customVocabulary: true,
883
+ summarization: true,
884
+ sentimentAnalysis: true,
885
+ entityDetection: true,
886
+ piiRedaction: true
887
+ };
888
+ this.baseUrl = "https://api.assemblyai.com/v2";
889
+ this.wsBaseUrl = "wss://api.assemblyai.com/v2/realtime/ws";
890
+ }
891
+ initialize(config) {
892
+ super.initialize(config);
893
+ this.client = import_axios2.default.create({
894
+ baseURL: config.baseUrl || this.baseUrl,
895
+ timeout: config.timeout || 6e4,
896
+ headers: {
897
+ authorization: config.apiKey,
898
+ "Content-Type": "application/json",
899
+ ...config.headers
900
+ }
901
+ });
902
+ }
903
+ /**
904
+ * Submit audio for transcription
905
+ *
906
+ * Sends audio to AssemblyAI API for transcription. If a webhook URL is provided,
907
+ * returns immediately with the job ID. Otherwise, polls until completion.
908
+ *
909
+ * @param audio - Audio input (currently only URL type supported)
910
+ * @param options - Transcription options
911
+ * @param options.language - Language code (e.g., 'en', 'en_us', 'es', 'fr')
912
+ * @param options.languageDetection - Enable automatic language detection
913
+ * @param options.diarization - Enable speaker identification (speaker_labels)
914
+ * @param options.speakersExpected - Number of expected speakers
915
+ * @param options.summarization - Generate text summary
916
+ * @param options.sentimentAnalysis - Analyze sentiment of transcription
917
+ * @param options.entityDetection - Detect named entities (people, places, etc.)
918
+ * @param options.piiRedaction - Redact personally identifiable information
919
+ * @param options.customVocabulary - Words to boost in recognition
920
+ * @param options.webhookUrl - Callback URL for async results
921
+ * @returns Normalized transcription response
922
+ * @throws {Error} If audio type is not 'url' (file/stream not yet supported)
923
+ *
924
+ * @example Simple transcription
925
+ * ```typescript
926
+ * const result = await adapter.transcribe({
927
+ * type: 'url',
928
+ * url: 'https://example.com/meeting.mp3'
929
+ * });
930
+ * ```
931
+ *
932
+ * @example With advanced features
933
+ * ```typescript
934
+ * const result = await adapter.transcribe({
935
+ * type: 'url',
936
+ * url: 'https://example.com/meeting.mp3'
937
+ * }, {
938
+ * language: 'en_us',
939
+ * diarization: true,
940
+ * speakersExpected: 3,
941
+ * summarization: true,
942
+ * sentimentAnalysis: true,
943
+ * entityDetection: true,
944
+ * customVocabulary: ['API', 'TypeScript', 'JavaScript']
945
+ * });
946
+ * ```
947
+ *
948
+ * @example With webhook (returns transcript ID immediately for polling)
949
+ * ```typescript
950
+ * // Submit transcription with webhook
951
+ * const result = await adapter.transcribe({
952
+ * type: 'url',
953
+ * url: 'https://example.com/meeting.mp3'
954
+ * }, {
955
+ * webhookUrl: 'https://myapp.com/webhook/transcription',
956
+ * language: 'en_us'
957
+ * });
958
+ *
959
+ * // Get transcript ID for polling
960
+ * const transcriptId = result.data?.id;
961
+ * console.log('Transcript ID:', transcriptId); // Use this to poll for status
962
+ *
963
+ * // Later: Poll for completion (if webhook fails or you want to check)
964
+ * const status = await adapter.getTranscript(transcriptId);
965
+ * if (status.data?.status === 'completed') {
966
+ * console.log('Transcript:', status.data.text);
967
+ * }
968
+ * ```
969
+ */
970
+ async transcribe(audio, options) {
971
+ this.validateConfig();
972
+ try {
973
+ const payload = this.buildTranscriptionRequest(audio, options);
974
+ const response = await this.client.post("/transcript", payload);
975
+ const transcriptId = response.data.id;
976
+ if (options?.webhookUrl) {
977
+ return {
978
+ success: true,
979
+ provider: this.name,
980
+ data: {
981
+ id: transcriptId,
982
+ text: "",
983
+ status: "queued"
984
+ },
985
+ raw: response.data
986
+ };
987
+ }
988
+ return await this.pollForCompletion(transcriptId);
989
+ } catch (error) {
990
+ return this.createErrorResponse(error);
991
+ }
992
+ }
993
+ /**
994
+ * Get transcription result by ID
995
+ */
996
+ async getTranscript(transcriptId) {
997
+ this.validateConfig();
998
+ try {
999
+ const response = await this.client.get(`/transcript/${transcriptId}`);
1000
+ return this.normalizeResponse(response.data);
1001
+ } catch (error) {
1002
+ return this.createErrorResponse(error);
1003
+ }
1004
+ }
1005
+ /**
1006
+ * Build AssemblyAI transcription request from unified options
1007
+ */
1008
+ buildTranscriptionRequest(audio, options) {
1009
+ let audioUrl;
1010
+ if (audio.type === "url") {
1011
+ audioUrl = audio.url;
1012
+ } else {
1013
+ throw new Error(
1014
+ "AssemblyAI adapter currently only supports URL-based audio input. Use audio.type='url'"
1015
+ );
1016
+ }
1017
+ const request = {
1018
+ audio_url: audioUrl
1019
+ };
1020
+ if (options) {
1021
+ if (options.language) {
1022
+ const languageCode = options.language.includes("_") ? options.language : `${options.language}_us`;
1023
+ request.language_code = languageCode;
1024
+ }
1025
+ if (options.languageDetection) {
1026
+ request.language_detection = true;
1027
+ }
1028
+ if (options.diarization) {
1029
+ request.speaker_labels = true;
1030
+ if (options.speakersExpected) {
1031
+ request.speakers_expected = options.speakersExpected;
1032
+ }
1033
+ }
1034
+ if (options.customVocabulary && options.customVocabulary.length > 0) {
1035
+ request.word_boost = options.customVocabulary;
1036
+ request.boost_param = "high";
1037
+ }
1038
+ if (options.summarization) {
1039
+ request.summarization = true;
1040
+ request.summary_model = "informative";
1041
+ request.summary_type = "bullets";
1042
+ }
1043
+ if (options.sentimentAnalysis) {
1044
+ request.sentiment_analysis = true;
1045
+ }
1046
+ if (options.entityDetection) {
1047
+ request.entity_detection = true;
1048
+ }
1049
+ if (options.piiRedaction) {
1050
+ request.redact_pii = true;
1051
+ }
1052
+ if (options.webhookUrl) {
1053
+ request.webhook_url = options.webhookUrl;
1054
+ }
1055
+ request.punctuate = true;
1056
+ request.format_text = true;
1057
+ }
1058
+ return request;
1059
+ }
1060
+ /**
1061
+ * Normalize AssemblyAI response to unified format
1062
+ */
1063
+ normalizeResponse(response) {
1064
+ let status;
1065
+ switch (response.status) {
1066
+ case "queued":
1067
+ status = "queued";
1068
+ break;
1069
+ case "processing":
1070
+ status = "processing";
1071
+ break;
1072
+ case "completed":
1073
+ status = "completed";
1074
+ break;
1075
+ case "error":
1076
+ status = "error";
1077
+ break;
1078
+ default:
1079
+ status = "queued";
1080
+ }
1081
+ if (response.status === "error") {
1082
+ return {
1083
+ success: false,
1084
+ provider: this.name,
1085
+ error: {
1086
+ code: "TRANSCRIPTION_ERROR",
1087
+ message: response.error || "Transcription failed"
1088
+ },
1089
+ raw: response
1090
+ };
1091
+ }
1092
+ return {
1093
+ success: true,
1094
+ provider: this.name,
1095
+ data: {
1096
+ id: response.id,
1097
+ text: response.text || "",
1098
+ confidence: response.confidence !== null ? response.confidence : void 0,
1099
+ status,
1100
+ language: response.language_code,
1101
+ duration: response.audio_duration ? response.audio_duration / 1e3 : void 0,
1102
+ // Convert ms to seconds
1103
+ speakers: this.extractSpeakers(response),
1104
+ words: this.extractWords(response),
1105
+ utterances: this.extractUtterances(response),
1106
+ summary: response.summary || void 0,
1107
+ metadata: {
1108
+ audioUrl: response.audio_url,
1109
+ entities: response.entities,
1110
+ sentimentAnalysis: response.sentiment_analysis_results,
1111
+ contentModeration: response.content_safety_labels
1112
+ }
1113
+ },
1114
+ raw: response
1115
+ };
1116
+ }
1117
+ /**
1118
+ * Extract speaker information from AssemblyAI response
1119
+ */
1120
+ extractSpeakers(transcript) {
1121
+ if (!transcript.utterances || transcript.utterances.length === 0) {
1122
+ return void 0;
1123
+ }
1124
+ const speakerSet = /* @__PURE__ */ new Set();
1125
+ transcript.utterances.forEach((utterance) => {
1126
+ if (utterance.speaker) {
1127
+ speakerSet.add(utterance.speaker);
1128
+ }
1129
+ });
1130
+ if (speakerSet.size === 0) {
1131
+ return void 0;
1132
+ }
1133
+ return Array.from(speakerSet).map((speakerId) => ({
1134
+ id: speakerId,
1135
+ label: speakerId
1136
+ // AssemblyAI uses format like "A", "B", "C"
1137
+ }));
1138
+ }
1139
+ /**
1140
+ * Extract word timestamps from AssemblyAI response
1141
+ */
1142
+ extractWords(transcript) {
1143
+ if (!transcript.words || transcript.words.length === 0) {
1144
+ return void 0;
1145
+ }
1146
+ return transcript.words.map((word) => ({
1147
+ text: word.text,
1148
+ start: word.start / 1e3,
1149
+ // Convert ms to seconds
1150
+ end: word.end / 1e3,
1151
+ // Convert ms to seconds
1152
+ confidence: word.confidence,
1153
+ speaker: word.speaker || void 0
1154
+ }));
1155
+ }
1156
+ /**
1157
+ * Extract utterances from AssemblyAI response
1158
+ */
1159
+ extractUtterances(transcript) {
1160
+ if (!transcript.utterances || transcript.utterances.length === 0) {
1161
+ return void 0;
1162
+ }
1163
+ return transcript.utterances.map((utterance) => ({
1164
+ text: utterance.text,
1165
+ start: utterance.start / 1e3,
1166
+ // Convert ms to seconds
1167
+ end: utterance.end / 1e3,
1168
+ // Convert ms to seconds
1169
+ speaker: utterance.speaker || void 0,
1170
+ confidence: utterance.confidence,
1171
+ words: utterance.words.map((word) => ({
1172
+ text: word.text,
1173
+ start: word.start / 1e3,
1174
+ end: word.end / 1e3,
1175
+ confidence: word.confidence
1176
+ }))
1177
+ }));
1178
+ }
1179
+ /**
1180
+ * Poll for transcription completion
1181
+ */
1182
+ async pollForCompletion(transcriptId, maxAttempts = 60, intervalMs = 3e3) {
1183
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
1184
+ const result = await this.getTranscript(transcriptId);
1185
+ if (!result.success) {
1186
+ return result;
1187
+ }
1188
+ const status = result.data?.status;
1189
+ if (status === "completed") {
1190
+ return result;
1191
+ }
1192
+ if (status === "error") {
1193
+ return {
1194
+ success: false,
1195
+ provider: this.name,
1196
+ error: {
1197
+ code: "TRANSCRIPTION_ERROR",
1198
+ message: "Transcription failed"
1199
+ },
1200
+ raw: result.raw
1201
+ };
1202
+ }
1203
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
1204
+ }
1205
+ return {
1206
+ success: false,
1207
+ provider: this.name,
1208
+ error: {
1209
+ code: "POLLING_TIMEOUT",
1210
+ message: `Transcription did not complete after ${maxAttempts} attempts`
1211
+ }
1212
+ };
1213
+ }
1214
+ /**
1215
+ * Stream audio for real-time transcription
1216
+ *
1217
+ * Creates a WebSocket connection to AssemblyAI for streaming transcription.
1218
+ * First obtains a temporary token, then connects and streams audio chunks.
1219
+ *
1220
+ * @param options - Streaming configuration options
1221
+ * @param callbacks - Event callbacks for transcription results
1222
+ * @returns Promise that resolves with a StreamingSession
1223
+ *
1224
+ * @example Real-time streaming
1225
+ * ```typescript
1226
+ * const session = await adapter.transcribeStream({
1227
+ * encoding: 'pcm_s16le',
1228
+ * sampleRate: 16000,
1229
+ * language: 'en',
1230
+ * interimResults: true
1231
+ * }, {
1232
+ * onOpen: () => console.log('Connected'),
1233
+ * onTranscript: (event) => {
1234
+ * if (event.isFinal) {
1235
+ * console.log('Final:', event.text);
1236
+ * } else {
1237
+ * console.log('Interim:', event.text);
1238
+ * }
1239
+ * },
1240
+ * onError: (error) => console.error('Error:', error),
1241
+ * onClose: () => console.log('Disconnected')
1242
+ * });
1243
+ *
1244
+ * // Send audio chunks
1245
+ * const audioChunk = getAudioChunk(); // Your audio source
1246
+ * await session.sendAudio({ data: audioChunk });
1247
+ *
1248
+ * // Close when done
1249
+ * await session.close();
1250
+ * ```
1251
+ */
1252
+ async transcribeStream(options, callbacks) {
1253
+ this.validateConfig();
1254
+ const tokenResponse = await this.client.post("/realtime/token", {
1255
+ expires_in: 3600
1256
+ // Token expires in 1 hour
1257
+ });
1258
+ const token = tokenResponse.data.token;
1259
+ const wsUrl = `${this.wsBaseUrl}?sample_rate=${options?.sampleRate || 16e3}&token=${token}`;
1260
+ const ws = new import_ws2.default(wsUrl);
1261
+ let sessionStatus = "connecting";
1262
+ const sessionId = `assemblyai-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1263
+ ws.on("open", () => {
1264
+ sessionStatus = "open";
1265
+ callbacks?.onOpen?.();
1266
+ });
1267
+ ws.on("message", (data) => {
1268
+ try {
1269
+ const message = JSON.parse(data.toString());
1270
+ if (message.message_type === "SessionBegins") {
1271
+ callbacks?.onMetadata?.({
1272
+ sessionId: message.session_id,
1273
+ expiresAt: message.expires_at
1274
+ });
1275
+ } else if (message.message_type === "PartialTranscript") {
1276
+ callbacks?.onTranscript?.({
1277
+ type: "transcript",
1278
+ text: message.text || "",
1279
+ isFinal: false,
1280
+ confidence: message.confidence,
1281
+ words: message.words?.map((word) => ({
1282
+ text: word.text,
1283
+ start: word.start / 1e3,
1284
+ end: word.end / 1e3,
1285
+ confidence: word.confidence
1286
+ })),
1287
+ data: message
1288
+ });
1289
+ } else if (message.message_type === "FinalTranscript") {
1290
+ callbacks?.onTranscript?.({
1291
+ type: "transcript",
1292
+ text: message.text || "",
1293
+ isFinal: true,
1294
+ confidence: message.confidence,
1295
+ words: message.words?.map((word) => ({
1296
+ text: word.text,
1297
+ start: word.start / 1e3,
1298
+ end: word.end / 1e3,
1299
+ confidence: word.confidence
1300
+ })),
1301
+ data: message
1302
+ });
1303
+ } else if (message.message_type === "SessionTerminated") {
1304
+ callbacks?.onMetadata?.({ terminated: true });
1305
+ }
1306
+ } catch (error) {
1307
+ callbacks?.onError?.({
1308
+ code: "PARSE_ERROR",
1309
+ message: "Failed to parse WebSocket message",
1310
+ details: error
1311
+ });
1312
+ }
1313
+ });
1314
+ ws.on("error", (error) => {
1315
+ callbacks?.onError?.({
1316
+ code: "WEBSOCKET_ERROR",
1317
+ message: error.message,
1318
+ details: error
1319
+ });
1320
+ });
1321
+ ws.on("close", (code, reason) => {
1322
+ sessionStatus = "closed";
1323
+ callbacks?.onClose?.(code, reason.toString());
1324
+ });
1325
+ await new Promise((resolve, reject) => {
1326
+ const timeout = setTimeout(() => {
1327
+ reject(new Error("WebSocket connection timeout"));
1328
+ }, 1e4);
1329
+ ws.once("open", () => {
1330
+ clearTimeout(timeout);
1331
+ resolve();
1332
+ });
1333
+ ws.once("error", (error) => {
1334
+ clearTimeout(timeout);
1335
+ reject(error);
1336
+ });
1337
+ });
1338
+ return {
1339
+ id: sessionId,
1340
+ provider: this.name,
1341
+ createdAt: /* @__PURE__ */ new Date(),
1342
+ getStatus: () => sessionStatus,
1343
+ sendAudio: async (chunk) => {
1344
+ if (sessionStatus !== "open") {
1345
+ throw new Error(`Cannot send audio: session is ${sessionStatus}`);
1346
+ }
1347
+ if (ws.readyState !== import_ws2.default.OPEN) {
1348
+ throw new Error("WebSocket is not open");
1349
+ }
1350
+ const base64Audio = chunk.data.toString("base64");
1351
+ ws.send(
1352
+ JSON.stringify({
1353
+ audio_data: base64Audio
1354
+ })
1355
+ );
1356
+ if (chunk.isLast) {
1357
+ ws.send(
1358
+ JSON.stringify({
1359
+ terminate_session: true
1360
+ })
1361
+ );
1362
+ }
1363
+ },
1364
+ close: async () => {
1365
+ if (sessionStatus === "closed" || sessionStatus === "closing") {
1366
+ return;
1367
+ }
1368
+ sessionStatus = "closing";
1369
+ if (ws.readyState === import_ws2.default.OPEN) {
1370
+ ws.send(
1371
+ JSON.stringify({
1372
+ terminate_session: true
1373
+ })
1374
+ );
1375
+ }
1376
+ return new Promise((resolve) => {
1377
+ const timeout = setTimeout(() => {
1378
+ ws.terminate();
1379
+ resolve();
1380
+ }, 5e3);
1381
+ ws.close();
1382
+ ws.once("close", () => {
1383
+ clearTimeout(timeout);
1384
+ sessionStatus = "closed";
1385
+ resolve();
1386
+ });
1387
+ });
1388
+ }
1389
+ };
1390
+ }
1391
+ };
1392
+ function createAssemblyAIAdapter(config) {
1393
+ const adapter = new AssemblyAIAdapter();
1394
+ adapter.initialize(config);
1395
+ return adapter;
1396
+ }
1397
+
1398
+ // src/adapters/deepgram-adapter.ts
1399
+ var import_axios3 = __toESM(require("axios"));
1400
+ var import_ws3 = __toESM(require("ws"));
1401
+ var DeepgramAdapter = class extends BaseAdapter {
1402
+ constructor() {
1403
+ super(...arguments);
1404
+ this.name = "deepgram";
1405
+ this.capabilities = {
1406
+ streaming: true,
1407
+ diarization: true,
1408
+ wordTimestamps: true,
1409
+ languageDetection: true,
1410
+ customVocabulary: true,
1411
+ summarization: true,
1412
+ sentimentAnalysis: true,
1413
+ entityDetection: true,
1414
+ piiRedaction: true
1415
+ };
1416
+ this.baseUrl = "https://api.deepgram.com/v1";
1417
+ this.wsBaseUrl = "wss://api.deepgram.com/v1/listen";
1418
+ }
1419
+ initialize(config) {
1420
+ super.initialize(config);
1421
+ this.client = import_axios3.default.create({
1422
+ baseURL: config.baseUrl || this.baseUrl,
1423
+ timeout: config.timeout || 6e4,
1424
+ headers: {
1425
+ Authorization: `Token ${config.apiKey}`,
1426
+ "Content-Type": "application/json",
1427
+ ...config.headers
1428
+ }
1429
+ });
1430
+ }
1431
+ /**
1432
+ * Submit audio for transcription
1433
+ *
1434
+ * Sends audio to Deepgram API for transcription. Deepgram processes
1435
+ * synchronously and returns results immediately (no polling required).
1436
+ *
1437
+ * @param audio - Audio input (URL or file buffer)
1438
+ * @param options - Transcription options
1439
+ * @param options.language - Language code (e.g., 'en', 'es', 'fr')
1440
+ * @param options.languageDetection - Enable automatic language detection
1441
+ * @param options.diarization - Enable speaker identification (diarize)
1442
+ * @param options.speakersExpected - Expected number of speakers
1443
+ * @param options.summarization - Generate text summary
1444
+ * @param options.sentimentAnalysis - Analyze sentiment
1445
+ * @param options.entityDetection - Detect named entities
1446
+ * @param options.piiRedaction - Redact personally identifiable information
1447
+ * @param options.customVocabulary - Keywords to boost in recognition
1448
+ * @param options.webhookUrl - Callback URL for async processing
1449
+ * @returns Normalized transcription response
1450
+ *
1451
+ * @example Simple transcription
1452
+ * ```typescript
1453
+ * const result = await adapter.transcribe({
1454
+ * type: 'url',
1455
+ * url: 'https://example.com/meeting.mp3'
1456
+ * });
1457
+ * ```
1458
+ *
1459
+ * @example With advanced features
1460
+ * ```typescript
1461
+ * const result = await adapter.transcribe({
1462
+ * type: 'url',
1463
+ * url: 'https://example.com/meeting.mp3'
1464
+ * }, {
1465
+ * language: 'en',
1466
+ * diarization: true,
1467
+ * summarization: true,
1468
+ * sentimentAnalysis: true,
1469
+ * entityDetection: true,
1470
+ * customVocabulary: ['API', 'TypeScript', 'JavaScript']
1471
+ * });
1472
+ * ```
1473
+ */
1474
+ async transcribe(audio, options) {
1475
+ this.validateConfig();
1476
+ try {
1477
+ const params = this.buildTranscriptionParams(options);
1478
+ let response;
1479
+ if (audio.type === "url") {
1480
+ response = await this.client.post(
1481
+ "/listen",
1482
+ { url: audio.url },
1483
+ { params }
1484
+ ).then((res) => res.data);
1485
+ } else if (audio.type === "file") {
1486
+ response = await this.client.post("/listen", audio.file, {
1487
+ params,
1488
+ headers: {
1489
+ "Content-Type": "audio/*"
1490
+ }
1491
+ }).then((res) => res.data);
1492
+ } else {
1493
+ throw new Error(
1494
+ "Deepgram adapter does not support stream type for pre-recorded transcription. Use transcribeStream() for real-time streaming."
1495
+ );
1496
+ }
1497
+ return this.normalizeResponse(response);
1498
+ } catch (error) {
1499
+ return this.createErrorResponse(error);
1500
+ }
1501
+ }
1502
+ /**
1503
+ * Get transcription result by ID
1504
+ *
1505
+ * Note: Deepgram processes synchronously, so this method is primarily
1506
+ * for retrieving cached results if you've stored the request ID.
1507
+ * The initial transcribe() call already returns complete results.
1508
+ *
1509
+ * @param transcriptId - Request ID from Deepgram
1510
+ * @returns Normalized transcription response
1511
+ */
1512
+ async getTranscript(transcriptId) {
1513
+ this.validateConfig();
1514
+ return {
1515
+ success: false,
1516
+ provider: this.name,
1517
+ error: {
1518
+ code: "NOT_SUPPORTED",
1519
+ message: "Deepgram returns transcription results immediately. Store the response from transcribe() instead of using getTranscript()."
1520
+ }
1521
+ };
1522
+ }
1523
+ /**
1524
+ * Build Deepgram transcription parameters from unified options
1525
+ */
1526
+ buildTranscriptionParams(options) {
1527
+ const params = {};
1528
+ if (!options) {
1529
+ return params;
1530
+ }
1531
+ if (options.language) {
1532
+ params.language = options.language;
1533
+ }
1534
+ if (options.languageDetection) {
1535
+ params.detect_language = true;
1536
+ }
1537
+ if (options.diarization) {
1538
+ params.diarize = true;
1539
+ }
1540
+ if (options.customVocabulary && options.customVocabulary.length > 0) {
1541
+ params.keywords = options.customVocabulary;
1542
+ }
1543
+ if (options.summarization) {
1544
+ params.summarize = true;
1545
+ }
1546
+ if (options.sentimentAnalysis) {
1547
+ params.sentiment = true;
1548
+ }
1549
+ if (options.entityDetection) {
1550
+ params.detect_entities = true;
1551
+ }
1552
+ if (options.piiRedaction) {
1553
+ params.redact = true;
1554
+ }
1555
+ if (options.webhookUrl) {
1556
+ params.callback = options.webhookUrl;
1557
+ }
1558
+ params.punctuate = true;
1559
+ params.utterances = true;
1560
+ params.smart_format = true;
1561
+ return params;
1562
+ }
1563
+ /**
1564
+ * Normalize Deepgram response to unified format
1565
+ */
1566
+ normalizeResponse(response) {
1567
+ const channel = response.results.channels?.[0];
1568
+ const alternative = channel?.alternatives?.[0];
1569
+ if (!alternative) {
1570
+ return {
1571
+ success: false,
1572
+ provider: this.name,
1573
+ error: {
1574
+ code: "NO_RESULTS",
1575
+ message: "No transcription results returned by Deepgram"
1576
+ },
1577
+ raw: response
1578
+ };
1579
+ }
1580
+ return {
1581
+ success: true,
1582
+ provider: this.name,
1583
+ data: {
1584
+ id: response.metadata?.request_id || "",
1585
+ text: alternative.transcript || "",
1586
+ confidence: alternative.confidence,
1587
+ status: "completed",
1588
+ // Deepgram returns completed results immediately
1589
+ language: channel?.detected_language || void 0,
1590
+ duration: response.metadata?.duration,
1591
+ speakers: this.extractSpeakers(response),
1592
+ words: this.extractWords(alternative),
1593
+ utterances: this.extractUtterances(response),
1594
+ summary: this.extractSummary(alternative),
1595
+ metadata: {
1596
+ modelInfo: response.metadata?.model_info,
1597
+ channels: response.metadata?.channels,
1598
+ sentiment: response.results.sentiments,
1599
+ intents: response.results.intents,
1600
+ topics: response.results.topics
1601
+ }
1602
+ },
1603
+ raw: response
1604
+ };
1605
+ }
1606
+ /**
1607
+ * Extract speaker information from Deepgram response
1608
+ */
1609
+ extractSpeakers(response) {
1610
+ const utterances = response.results.utterances;
1611
+ if (!utterances || utterances.length === 0) {
1612
+ return void 0;
1613
+ }
1614
+ const speakerSet = /* @__PURE__ */ new Set();
1615
+ utterances.forEach((utterance) => {
1616
+ if (utterance.speaker !== void 0) {
1617
+ speakerSet.add(utterance.speaker);
1618
+ }
1619
+ });
1620
+ if (speakerSet.size === 0) {
1621
+ return void 0;
1622
+ }
1623
+ return Array.from(speakerSet).map((speakerId) => ({
1624
+ id: speakerId.toString(),
1625
+ label: `Speaker ${speakerId}`
1626
+ }));
1627
+ }
1628
+ /**
1629
+ * Extract word timestamps from Deepgram response
1630
+ */
1631
+ extractWords(alternative) {
1632
+ if (!alternative.words || alternative.words.length === 0) {
1633
+ return void 0;
1634
+ }
1635
+ return alternative.words.map(
1636
+ (word) => ({
1637
+ text: word.word || "",
1638
+ start: word.start || 0,
1639
+ end: word.end || 0,
1640
+ confidence: word.confidence,
1641
+ speaker: void 0
1642
+ // Speaker info is at utterance level, not word level
1643
+ })
1644
+ );
1645
+ }
1646
+ /**
1647
+ * Extract utterances from Deepgram response
1648
+ */
1649
+ extractUtterances(response) {
1650
+ const utterances = response.results.utterances;
1651
+ if (!utterances || utterances.length === 0) {
1652
+ return void 0;
1653
+ }
1654
+ return utterances.map((utterance) => ({
1655
+ text: utterance.transcript || "",
1656
+ start: utterance.start || 0,
1657
+ end: utterance.end || 0,
1658
+ speaker: utterance.speaker?.toString(),
1659
+ confidence: utterance.confidence,
1660
+ words: utterance.words?.map((word) => ({
1661
+ text: word.word || "",
1662
+ start: word.start || 0,
1663
+ end: word.end || 0,
1664
+ confidence: word.confidence
1665
+ }))
1666
+ }));
1667
+ }
1668
+ /**
1669
+ * Extract summary from Deepgram response
1670
+ */
1671
+ extractSummary(alternative) {
1672
+ if (!alternative.summaries || alternative.summaries.length === 0) {
1673
+ return void 0;
1674
+ }
1675
+ return alternative.summaries.map((summary) => summary.summary).filter(Boolean).join(" ");
1676
+ }
1677
+ /**
1678
+ * Stream audio for real-time transcription
1679
+ *
1680
+ * Creates a WebSocket connection to Deepgram for streaming transcription.
1681
+ * Send audio chunks via session.sendAudio() and receive results via callbacks.
1682
+ *
1683
+ * @param options - Streaming configuration options
1684
+ * @param callbacks - Event callbacks for transcription results
1685
+ * @returns Promise that resolves with a StreamingSession
1686
+ *
1687
+ * @example Real-time streaming
1688
+ * ```typescript
1689
+ * const session = await adapter.transcribeStream({
1690
+ * encoding: 'linear16',
1691
+ * sampleRate: 16000,
1692
+ * channels: 1,
1693
+ * language: 'en',
1694
+ * diarization: true,
1695
+ * interimResults: true
1696
+ * }, {
1697
+ * onOpen: () => console.log('Connected'),
1698
+ * onTranscript: (event) => {
1699
+ * if (event.isFinal) {
1700
+ * console.log('Final:', event.text);
1701
+ * } else {
1702
+ * console.log('Interim:', event.text);
1703
+ * }
1704
+ * },
1705
+ * onError: (error) => console.error('Error:', error),
1706
+ * onClose: () => console.log('Disconnected')
1707
+ * });
1708
+ *
1709
+ * // Send audio chunks
1710
+ * const audioChunk = getAudioChunk(); // Your audio source
1711
+ * await session.sendAudio({ data: audioChunk });
1712
+ *
1713
+ * // Close when done
1714
+ * await session.close();
1715
+ * ```
1716
+ */
1717
+ async transcribeStream(options, callbacks) {
1718
+ this.validateConfig();
1719
+ const params = new URLSearchParams();
1720
+ if (options?.encoding) params.append("encoding", options.encoding);
1721
+ if (options?.sampleRate) params.append("sample_rate", options.sampleRate.toString());
1722
+ if (options?.channels) params.append("channels", options.channels.toString());
1723
+ if (options?.language) params.append("language", options.language);
1724
+ if (options?.languageDetection) params.append("detect_language", "true");
1725
+ if (options?.diarization) params.append("diarize", "true");
1726
+ if (options?.interimResults) params.append("interim_results", "true");
1727
+ if (options?.summarization) params.append("summarize", "true");
1728
+ if (options?.sentimentAnalysis) params.append("sentiment", "true");
1729
+ if (options?.entityDetection) params.append("detect_entities", "true");
1730
+ if (options?.piiRedaction) params.append("redact", "pii");
1731
+ if (options?.customVocabulary && options.customVocabulary.length > 0) {
1732
+ params.append("keywords", options.customVocabulary.join(","));
1733
+ }
1734
+ const wsUrl = `${this.wsBaseUrl}?${params.toString()}`;
1735
+ const ws = new import_ws3.default(wsUrl, {
1736
+ headers: {
1737
+ Authorization: `Token ${this.config.apiKey}`
1738
+ }
1739
+ });
1740
+ let sessionStatus = "connecting";
1741
+ const sessionId = `deepgram-${Date.now()}-${Math.random().toString(36).substring(7)}`;
1742
+ ws.on("open", () => {
1743
+ sessionStatus = "open";
1744
+ callbacks?.onOpen?.();
1745
+ });
1746
+ ws.on("message", (data) => {
1747
+ try {
1748
+ const message = JSON.parse(data.toString());
1749
+ if (message.type === "Results") {
1750
+ const result = message;
1751
+ const channel = result.channel?.alternatives?.[0];
1752
+ if (channel) {
1753
+ const transcript = channel.transcript || "";
1754
+ const isFinal = message.is_final === true;
1755
+ const words = channel.words?.map((word) => ({
1756
+ text: word.word || "",
1757
+ start: word.start || 0,
1758
+ end: word.end || 0,
1759
+ confidence: word.confidence
1760
+ }));
1761
+ callbacks?.onTranscript?.({
1762
+ type: "transcript",
1763
+ text: transcript,
1764
+ isFinal,
1765
+ words,
1766
+ confidence: channel.confidence,
1767
+ data: result
1768
+ });
1769
+ }
1770
+ } else if (message.type === "UtteranceEnd") {
1771
+ callbacks?.onMetadata?.(message);
1772
+ } else if (message.type === "Metadata") {
1773
+ callbacks?.onMetadata?.(message);
1774
+ }
1775
+ } catch (error) {
1776
+ callbacks?.onError?.({
1777
+ code: "PARSE_ERROR",
1778
+ message: "Failed to parse WebSocket message",
1779
+ details: error
1780
+ });
1781
+ }
1782
+ });
1783
+ ws.on("error", (error) => {
1784
+ callbacks?.onError?.({
1785
+ code: "WEBSOCKET_ERROR",
1786
+ message: error.message,
1787
+ details: error
1788
+ });
1789
+ });
1790
+ ws.on("close", (code, reason) => {
1791
+ sessionStatus = "closed";
1792
+ callbacks?.onClose?.(code, reason.toString());
1793
+ });
1794
+ await new Promise((resolve, reject) => {
1795
+ const timeout = setTimeout(() => {
1796
+ reject(new Error("WebSocket connection timeout"));
1797
+ }, 1e4);
1798
+ ws.once("open", () => {
1799
+ clearTimeout(timeout);
1800
+ resolve();
1801
+ });
1802
+ ws.once("error", (error) => {
1803
+ clearTimeout(timeout);
1804
+ reject(error);
1805
+ });
1806
+ });
1807
+ return {
1808
+ id: sessionId,
1809
+ provider: this.name,
1810
+ createdAt: /* @__PURE__ */ new Date(),
1811
+ getStatus: () => sessionStatus,
1812
+ sendAudio: async (chunk) => {
1813
+ if (sessionStatus !== "open") {
1814
+ throw new Error(`Cannot send audio: session is ${sessionStatus}`);
1815
+ }
1816
+ if (ws.readyState !== import_ws3.default.OPEN) {
1817
+ throw new Error("WebSocket is not open");
1818
+ }
1819
+ ws.send(chunk.data);
1820
+ if (chunk.isLast) {
1821
+ ws.send(JSON.stringify({ type: "CloseStream" }));
1822
+ }
1823
+ },
1824
+ close: async () => {
1825
+ if (sessionStatus === "closed" || sessionStatus === "closing") {
1826
+ return;
1827
+ }
1828
+ sessionStatus = "closing";
1829
+ if (ws.readyState === import_ws3.default.OPEN) {
1830
+ ws.send(JSON.stringify({ type: "CloseStream" }));
1831
+ }
1832
+ return new Promise((resolve) => {
1833
+ const timeout = setTimeout(() => {
1834
+ ws.terminate();
1835
+ resolve();
1836
+ }, 5e3);
1837
+ ws.close();
1838
+ ws.once("close", () => {
1839
+ clearTimeout(timeout);
1840
+ sessionStatus = "closed";
1841
+ resolve();
1842
+ });
1843
+ });
1844
+ }
1845
+ };
1846
+ }
1847
+ };
1848
+ function createDeepgramAdapter(config) {
1849
+ const adapter = new DeepgramAdapter();
1850
+ adapter.initialize(config);
1851
+ return adapter;
1852
+ }
1853
+
1854
+ // src/adapters/azure-stt-adapter.ts
1855
+ var import_axios4 = __toESM(require("axios"));
1856
+ var AzureSTTAdapter = class extends BaseAdapter {
1857
+ constructor() {
1858
+ super(...arguments);
1859
+ this.name = "azure-stt";
1860
+ this.capabilities = {
1861
+ streaming: false,
1862
+ // Batch transcription only
1863
+ diarization: true,
1864
+ wordTimestamps: true,
1865
+ languageDetection: false,
1866
+ customVocabulary: true,
1867
+ summarization: false,
1868
+ sentimentAnalysis: false,
1869
+ entityDetection: false,
1870
+ piiRedaction: false
1871
+ };
1872
+ }
1873
+ initialize(config) {
1874
+ super.initialize(config);
1875
+ this.region = config.region || "eastus";
1876
+ this.baseUrl = config.baseUrl || `https://${this.region}.api.cognitive.microsoft.com/speechtotext/v3.1`;
1877
+ this.client = import_axios4.default.create({
1878
+ baseURL: this.baseUrl,
1879
+ timeout: config.timeout || 6e4,
1880
+ headers: {
1881
+ "Ocp-Apim-Subscription-Key": config.apiKey,
1882
+ "Content-Type": "application/json",
1883
+ ...config.headers
1884
+ }
1885
+ });
1886
+ }
1887
+ /**
1888
+ * Submit audio for transcription
1889
+ *
1890
+ * Azure Speech-to-Text uses batch transcription which processes asynchronously.
1891
+ * You need to poll getTranscript() to retrieve the completed transcription.
1892
+ *
1893
+ * @param audio - Audio input (URL only for batch transcription)
1894
+ * @param options - Transcription options
1895
+ * @returns Response with transcription ID for polling
1896
+ */
1897
+ async transcribe(audio, options) {
1898
+ this.validateConfig();
1899
+ if (audio.type !== "url") {
1900
+ return {
1901
+ success: false,
1902
+ provider: this.name,
1903
+ error: {
1904
+ code: "INVALID_INPUT",
1905
+ message: "Azure Speech-to-Text batch transcription only supports URL input"
1906
+ }
1907
+ };
1908
+ }
1909
+ try {
1910
+ const transcriptionRequest = {
1911
+ displayName: options?.metadata?.displayName || "SDK Transcription",
1912
+ description: options?.metadata?.description || "",
1913
+ locale: options?.language || "en-US",
1914
+ contentUrls: [audio.url],
1915
+ properties: this.buildTranscriptionProperties(options)
1916
+ };
1917
+ const response = await this.client.post(
1918
+ "/transcriptions",
1919
+ transcriptionRequest
1920
+ );
1921
+ const transcription = response.data;
1922
+ return {
1923
+ success: true,
1924
+ provider: this.name,
1925
+ data: {
1926
+ id: transcription.self?.split("/").pop() || "",
1927
+ text: "",
1928
+ // Will be populated after polling
1929
+ status: this.normalizeStatus(transcription.status),
1930
+ language: transcription.locale,
1931
+ createdAt: transcription.createdDateTime
1932
+ },
1933
+ raw: transcription
1934
+ };
1935
+ } catch (error) {
1936
+ return this.createErrorResponse(error);
1937
+ }
1938
+ }
1939
+ /**
1940
+ * Get transcription result by ID
1941
+ *
1942
+ * Poll this method to check transcription status and retrieve results.
1943
+ *
1944
+ * @param transcriptId - Transcription ID from Azure
1945
+ * @returns Transcription response with status and results
1946
+ */
1947
+ async getTranscript(transcriptId) {
1948
+ this.validateConfig();
1949
+ try {
1950
+ const statusResponse = await this.client.get(
1951
+ `/transcriptions/${transcriptId}`
1952
+ );
1953
+ const transcription = statusResponse.data;
1954
+ const status = this.normalizeStatus(transcription.status);
1955
+ if (status !== "completed") {
1956
+ return {
1957
+ success: true,
1958
+ provider: this.name,
1959
+ data: {
1960
+ id: transcriptId,
1961
+ text: "",
1962
+ status,
1963
+ language: transcription.locale,
1964
+ createdAt: transcription.createdDateTime
1965
+ },
1966
+ raw: transcription
1967
+ };
1968
+ }
1969
+ if (!transcription.links?.files) {
1970
+ return {
1971
+ success: false,
1972
+ provider: this.name,
1973
+ error: {
1974
+ code: "NO_RESULTS",
1975
+ message: "Transcription completed but no result files available"
1976
+ },
1977
+ raw: transcription
1978
+ };
1979
+ }
1980
+ const filesResponse = await this.client.get(transcription.links.files);
1981
+ const files = filesResponse.data?.values || [];
1982
+ const resultFile = files.find((file) => file.kind === "Transcription");
1983
+ if (!resultFile?.links?.contentUrl) {
1984
+ return {
1985
+ success: false,
1986
+ provider: this.name,
1987
+ error: {
1988
+ code: "NO_RESULTS",
1989
+ message: "Transcription result file not found"
1990
+ },
1991
+ raw: transcription
1992
+ };
1993
+ }
1994
+ const contentResponse = await import_axios4.default.get(resultFile.links.contentUrl);
1995
+ const transcriptionData = contentResponse.data;
1996
+ return this.normalizeResponse(transcription, transcriptionData);
1997
+ } catch (error) {
1998
+ return this.createErrorResponse(error);
1999
+ }
2000
+ }
2001
+ /**
2002
+ * Build Azure-specific transcription properties
2003
+ */
2004
+ buildTranscriptionProperties(options) {
2005
+ const properties = {
2006
+ wordLevelTimestampsEnabled: options?.wordTimestamps ?? true,
2007
+ punctuationMode: "DictatedAndAutomatic",
2008
+ profanityFilterMode: "Masked"
2009
+ };
2010
+ if (options?.diarization) {
2011
+ properties.diarizationEnabled = true;
2012
+ if (options.speakersExpected) {
2013
+ properties.diarization = {
2014
+ speakers: {
2015
+ minCount: 1,
2016
+ maxCount: options.speakersExpected
2017
+ }
2018
+ };
2019
+ }
2020
+ }
2021
+ if (options?.customVocabulary && options.customVocabulary.length > 0) {
2022
+ properties.customProperties = {
2023
+ phrases: options.customVocabulary.join(",")
2024
+ };
2025
+ }
2026
+ return properties;
2027
+ }
2028
+ /**
2029
+ * Normalize Azure status to unified status
2030
+ */
2031
+ normalizeStatus(status) {
2032
+ const statusStr = status?.toString().toLowerCase() || "";
2033
+ if (statusStr.includes("succeeded")) return "completed";
2034
+ if (statusStr.includes("running")) return "processing";
2035
+ if (statusStr.includes("notstarted")) return "queued";
2036
+ if (statusStr.includes("failed")) return "error";
2037
+ return "queued";
2038
+ }
2039
+ /**
2040
+ * Normalize Azure transcription response to unified format
2041
+ */
2042
+ normalizeResponse(transcription, transcriptionData) {
2043
+ const combinedPhrases = transcriptionData.combinedRecognizedPhrases || [];
2044
+ const recognizedPhrases = transcriptionData.recognizedPhrases || [];
2045
+ const fullText = combinedPhrases.map((phrase) => phrase.display || phrase.lexical).join(" ") || "";
2046
+ const words = recognizedPhrases.flatMap(
2047
+ (phrase) => (phrase.nBest?.[0]?.words || []).map((word) => ({
2048
+ text: word.word,
2049
+ start: word.offsetInTicks / 1e7,
2050
+ // Convert ticks to seconds
2051
+ end: (word.offsetInTicks + word.durationInTicks) / 1e7,
2052
+ confidence: word.confidence,
2053
+ speaker: phrase.speaker !== void 0 ? phrase.speaker.toString() : void 0
2054
+ }))
2055
+ );
2056
+ const speakers = recognizedPhrases.length > 0 && recognizedPhrases[0].speaker !== void 0 ? Array.from(
2057
+ new Set(
2058
+ recognizedPhrases.map((p) => p.speaker).filter((s) => s !== void 0)
2059
+ )
2060
+ ).map((speakerId) => ({
2061
+ id: String(speakerId),
2062
+ label: `Speaker ${speakerId}`
2063
+ })) : void 0;
2064
+ return {
2065
+ success: true,
2066
+ provider: this.name,
2067
+ data: {
2068
+ id: transcription.self?.split("/").pop() || "",
2069
+ text: fullText,
2070
+ confidence: recognizedPhrases[0]?.nBest?.[0]?.confidence,
2071
+ status: "completed",
2072
+ language: transcription.locale,
2073
+ duration: transcriptionData.duration ? transcriptionData.duration / 1e7 : void 0,
2074
+ speakers,
2075
+ words: words.length > 0 ? words : void 0,
2076
+ createdAt: transcription.createdDateTime,
2077
+ completedAt: transcription.lastActionDateTime
2078
+ },
2079
+ raw: {
2080
+ transcription,
2081
+ transcriptionData
2082
+ }
2083
+ };
2084
+ }
2085
+ };
2086
+ function createAzureSTTAdapter(config) {
2087
+ const adapter = new AzureSTTAdapter();
2088
+ adapter.initialize(config);
2089
+ return adapter;
2090
+ }
2091
+
2092
+ // src/adapters/openai-whisper-adapter.ts
2093
+ var import_axios5 = __toESM(require("axios"));
2094
+ var OpenAIWhisperAdapter = class extends BaseAdapter {
2095
+ constructor() {
2096
+ super(...arguments);
2097
+ this.name = "openai-whisper";
2098
+ this.capabilities = {
2099
+ streaming: false,
2100
+ // Synchronous only (no streaming API for transcription)
2101
+ diarization: true,
2102
+ // Available with gpt-4o-transcribe-diarize model
2103
+ wordTimestamps: true,
2104
+ languageDetection: false,
2105
+ // Language should be provided for best accuracy
2106
+ customVocabulary: false,
2107
+ // Uses prompt instead
2108
+ summarization: false,
2109
+ sentimentAnalysis: false,
2110
+ entityDetection: false,
2111
+ piiRedaction: false
2112
+ };
2113
+ this.baseUrl = "https://api.openai.com/v1";
2114
+ }
2115
+ initialize(config) {
2116
+ super.initialize(config);
2117
+ this.baseUrl = config.baseUrl || this.baseUrl;
2118
+ this.client = import_axios5.default.create({
2119
+ baseURL: this.baseUrl,
2120
+ timeout: config.timeout || 12e4,
2121
+ // 2 minutes default (audio processing can take time)
2122
+ headers: {
2123
+ Authorization: `Bearer ${config.apiKey}`,
2124
+ "Content-Type": "multipart/form-data",
2125
+ ...config.headers
2126
+ }
2127
+ });
2128
+ }
2129
+ /**
2130
+ * Submit audio for transcription
2131
+ *
2132
+ * OpenAI Whisper API processes audio synchronously and returns results immediately.
2133
+ * Supports multiple models with different capabilities:
2134
+ * - whisper-1: Open source Whisper V2 model
2135
+ * - gpt-4o-transcribe: More accurate GPT-4o based transcription
2136
+ * - gpt-4o-mini-transcribe: Faster, cost-effective GPT-4o mini
2137
+ * - gpt-4o-transcribe-diarize: GPT-4o with speaker diarization
2138
+ *
2139
+ * @param audio - Audio input (URL or Buffer)
2140
+ * @param options - Transcription options
2141
+ * @returns Transcription response with full results
2142
+ */
2143
+ async transcribe(audio, options) {
2144
+ this.validateConfig();
2145
+ try {
2146
+ let audioData;
2147
+ let fileName = "audio.mp3";
2148
+ if (audio.type === "url") {
2149
+ const response2 = await import_axios5.default.get(audio.url, {
2150
+ responseType: "arraybuffer"
2151
+ });
2152
+ audioData = Buffer.from(response2.data);
2153
+ const urlPath = new URL(audio.url).pathname;
2154
+ const extractedName = urlPath.split("/").pop();
2155
+ if (extractedName) {
2156
+ fileName = extractedName;
2157
+ }
2158
+ } else if (audio.type === "file") {
2159
+ audioData = audio.file;
2160
+ fileName = audio.filename || fileName;
2161
+ } else {
2162
+ return {
2163
+ success: false,
2164
+ provider: this.name,
2165
+ error: {
2166
+ code: "INVALID_INPUT",
2167
+ message: "OpenAI Whisper only supports URL and File audio input (not stream)"
2168
+ }
2169
+ };
2170
+ }
2171
+ const model = this.selectModel(options);
2172
+ const isDiarization = model === "gpt-4o-transcribe-diarize";
2173
+ const needsWords = options?.wordTimestamps === true;
2174
+ const requestBody = {
2175
+ file: audioData,
2176
+ model
2177
+ };
2178
+ if (options?.language) {
2179
+ requestBody.language = options.language;
2180
+ }
2181
+ if (options?.metadata?.prompt) {
2182
+ requestBody.prompt = options.metadata.prompt;
2183
+ }
2184
+ if (options?.metadata?.temperature !== void 0) {
2185
+ requestBody.temperature = options.metadata.temperature;
2186
+ }
2187
+ if (isDiarization) {
2188
+ requestBody.response_format = "diarized_json";
2189
+ if (options?.metadata?.knownSpeakerNames) {
2190
+ requestBody["known_speaker_names"] = options.metadata.knownSpeakerNames;
2191
+ }
2192
+ if (options?.metadata?.knownSpeakerReferences) {
2193
+ requestBody["known_speaker_references"] = options.metadata.knownSpeakerReferences;
2194
+ }
2195
+ } else if (needsWords || options?.diarization) {
2196
+ requestBody.response_format = "verbose_json";
2197
+ if (needsWords) {
2198
+ requestBody.timestamp_granularities = ["word", "segment"];
2199
+ }
2200
+ } else {
2201
+ requestBody.response_format = "json";
2202
+ }
2203
+ const response = await this.client.post("/audio/transcriptions", requestBody, {
2204
+ headers: {
2205
+ "Content-Type": "multipart/form-data"
2206
+ }
2207
+ });
2208
+ return this.normalizeResponse(response.data, model, isDiarization);
2209
+ } catch (error) {
2210
+ return this.createErrorResponse(error);
2211
+ }
2212
+ }
2213
+ /**
2214
+ * OpenAI Whisper returns results synchronously, so getTranscript is not needed.
2215
+ * This method exists for interface compatibility but will return an error.
2216
+ */
2217
+ async getTranscript(transcriptId) {
2218
+ return {
2219
+ success: false,
2220
+ provider: this.name,
2221
+ error: {
2222
+ code: "NOT_SUPPORTED",
2223
+ message: "OpenAI Whisper processes transcriptions synchronously. Use transcribe() method directly."
2224
+ }
2225
+ };
2226
+ }
2227
+ /**
2228
+ * Select appropriate model based on transcription options
2229
+ */
2230
+ selectModel(options) {
2231
+ if (options?.metadata?.model) {
2232
+ return options.metadata.model;
2233
+ }
2234
+ if (options?.diarization) {
2235
+ return "gpt-4o-transcribe-diarize";
2236
+ }
2237
+ return "gpt-4o-transcribe";
2238
+ }
2239
+ /**
2240
+ * Normalize OpenAI response to unified format
2241
+ */
2242
+ normalizeResponse(response, model, isDiarization) {
2243
+ if ("text" in response && Object.keys(response).length === 1) {
2244
+ return {
2245
+ success: true,
2246
+ provider: this.name,
2247
+ data: {
2248
+ id: `openai-${Date.now()}`,
2249
+ text: response.text,
2250
+ status: "completed",
2251
+ language: void 0,
2252
+ confidence: void 0
2253
+ },
2254
+ raw: response
2255
+ };
2256
+ }
2257
+ if (isDiarization && "segments" in response) {
2258
+ const diarizedResponse = response;
2259
+ const speakerSet = new Set(diarizedResponse.segments.map((seg) => seg.speaker));
2260
+ const speakers = Array.from(speakerSet).map((speaker) => ({
2261
+ id: speaker,
2262
+ label: speaker
2263
+ // Already labeled by OpenAI (A, B, C or custom names)
2264
+ }));
2265
+ const utterances = diarizedResponse.segments.map((segment) => ({
2266
+ speaker: segment.speaker,
2267
+ text: segment.text,
2268
+ start: segment.start,
2269
+ end: segment.end,
2270
+ confidence: void 0
2271
+ }));
2272
+ return {
2273
+ success: true,
2274
+ provider: this.name,
2275
+ data: {
2276
+ id: `openai-${Date.now()}`,
2277
+ text: diarizedResponse.text,
2278
+ status: "completed",
2279
+ language: void 0,
2280
+ duration: diarizedResponse.duration,
2281
+ speakers,
2282
+ utterances
2283
+ },
2284
+ raw: response
2285
+ };
2286
+ }
2287
+ if ("duration" in response && "language" in response) {
2288
+ const verboseResponse = response;
2289
+ const words = verboseResponse.words?.map((word) => ({
2290
+ text: word.word,
2291
+ start: word.start,
2292
+ end: word.end,
2293
+ confidence: void 0
2294
+ }));
2295
+ return {
2296
+ success: true,
2297
+ provider: this.name,
2298
+ data: {
2299
+ id: `openai-${Date.now()}`,
2300
+ text: verboseResponse.text,
2301
+ status: "completed",
2302
+ language: verboseResponse.language,
2303
+ duration: verboseResponse.duration,
2304
+ words
2305
+ },
2306
+ raw: response
2307
+ };
2308
+ }
2309
+ return {
2310
+ success: true,
2311
+ provider: this.name,
2312
+ data: {
2313
+ id: `openai-${Date.now()}`,
2314
+ text: "text" in response ? response.text : "",
2315
+ status: "completed"
2316
+ },
2317
+ raw: response
2318
+ };
2319
+ }
2320
+ };
2321
+ function createOpenAIWhisperAdapter(config) {
2322
+ const adapter = new OpenAIWhisperAdapter();
2323
+ adapter.initialize(config);
2324
+ return adapter;
2325
+ }
2326
+
2327
+ // src/adapters/speechmatics-adapter.ts
2328
+ var import_axios6 = __toESM(require("axios"));
2329
+ var SpeechmaticsAdapter = class extends BaseAdapter {
2330
+ constructor() {
2331
+ super(...arguments);
2332
+ this.name = "speechmatics";
2333
+ this.capabilities = {
2334
+ streaming: false,
2335
+ // Batch only (streaming available via separate WebSocket API)
2336
+ diarization: true,
2337
+ wordTimestamps: true,
2338
+ languageDetection: false,
2339
+ customVocabulary: true,
2340
+ summarization: true,
2341
+ sentimentAnalysis: true,
2342
+ entityDetection: true,
2343
+ piiRedaction: false
2344
+ };
2345
+ this.baseUrl = "https://asr.api.speechmatics.com/v2";
2346
+ }
2347
+ initialize(config) {
2348
+ super.initialize(config);
2349
+ this.baseUrl = config.baseUrl || this.baseUrl;
2350
+ this.client = import_axios6.default.create({
2351
+ baseURL: this.baseUrl,
2352
+ timeout: config.timeout || 12e4,
2353
+ headers: {
2354
+ Authorization: `Bearer ${config.apiKey}`,
2355
+ ...config.headers
2356
+ }
2357
+ });
2358
+ }
2359
+ /**
2360
+ * Submit audio for transcription
2361
+ *
2362
+ * Speechmatics uses async batch processing. Returns a job ID immediately.
2363
+ * Poll getTranscript() to retrieve results.
2364
+ *
2365
+ * @param audio - Audio input (URL or file)
2366
+ * @param options - Transcription options
2367
+ * @returns Job submission response with ID for polling
2368
+ */
2369
+ async transcribe(audio, options) {
2370
+ this.validateConfig();
2371
+ try {
2372
+ const jobConfig = {
2373
+ type: "transcription",
2374
+ transcription_config: {
2375
+ language: options?.language || "en",
2376
+ operating_point: options?.metadata?.operating_point || "standard"
2377
+ }
2378
+ };
2379
+ if (options?.diarization) {
2380
+ jobConfig.transcription_config.diarization = "speaker";
2381
+ if (options.speakersExpected) {
2382
+ jobConfig.transcription_config.speaker_diarization_config = {
2383
+ max_speakers: options.speakersExpected
2384
+ };
2385
+ }
2386
+ }
2387
+ if (options?.sentimentAnalysis) {
2388
+ jobConfig.transcription_config.enable_sentiment_analysis = true;
2389
+ }
2390
+ if (options?.summarization && options?.metadata?.summary_type) {
2391
+ jobConfig.transcription_config.summarization_config = {
2392
+ type: options.metadata.summary_type,
2393
+ length: options.metadata.summary_length || "medium"
2394
+ };
2395
+ }
2396
+ if (options?.customVocabulary && options.customVocabulary.length > 0) {
2397
+ jobConfig.transcription_config.additional_vocab = options.customVocabulary;
2398
+ }
2399
+ let requestBody;
2400
+ let headers = {};
2401
+ if (audio.type === "url") {
2402
+ jobConfig.fetch_data = {
2403
+ url: audio.url
2404
+ };
2405
+ requestBody = { config: JSON.stringify(jobConfig) };
2406
+ headers = { "Content-Type": "application/json" };
2407
+ } else if (audio.type === "file") {
2408
+ requestBody = {
2409
+ config: JSON.stringify(jobConfig),
2410
+ data_file: audio.file
2411
+ };
2412
+ headers = { "Content-Type": "multipart/form-data" };
2413
+ } else {
2414
+ return {
2415
+ success: false,
2416
+ provider: this.name,
2417
+ error: {
2418
+ code: "INVALID_INPUT",
2419
+ message: "Speechmatics only supports URL and File audio input"
2420
+ }
2421
+ };
2422
+ }
2423
+ const response = await this.client.post("/jobs", requestBody, { headers });
2424
+ return {
2425
+ success: true,
2426
+ provider: this.name,
2427
+ data: {
2428
+ id: response.data.id,
2429
+ text: "",
2430
+ status: "queued",
2431
+ createdAt: response.data.created_at
2432
+ },
2433
+ raw: response.data
2434
+ };
2435
+ } catch (error) {
2436
+ return this.createErrorResponse(error);
2437
+ }
2438
+ }
2439
+ /**
2440
+ * Get transcription result by job ID
2441
+ *
2442
+ * Poll this method to check job status and retrieve completed transcription.
2443
+ *
2444
+ * @param transcriptId - Job ID from Speechmatics
2445
+ * @returns Transcription response with status and results
2446
+ */
2447
+ async getTranscript(transcriptId) {
2448
+ this.validateConfig();
2449
+ try {
2450
+ const statusResponse = await this.client.get(`/jobs/${transcriptId}`);
2451
+ const status = this.normalizeStatus(statusResponse.data.job.status);
2452
+ if (status !== "completed") {
2453
+ return {
2454
+ success: true,
2455
+ provider: this.name,
2456
+ data: {
2457
+ id: transcriptId,
2458
+ text: "",
2459
+ status,
2460
+ createdAt: statusResponse.data.job.created_at
2461
+ },
2462
+ raw: statusResponse.data
2463
+ };
2464
+ }
2465
+ const transcriptResponse = await this.client.get(
2466
+ `/jobs/${transcriptId}/transcript`
2467
+ );
2468
+ return this.normalizeResponse(transcriptResponse.data);
2469
+ } catch (error) {
2470
+ return this.createErrorResponse(error);
2471
+ }
2472
+ }
2473
+ /**
2474
+ * Normalize Speechmatics status to unified status
2475
+ */
2476
+ normalizeStatus(status) {
2477
+ switch (status) {
2478
+ case "running":
2479
+ return "processing";
2480
+ case "done":
2481
+ return "completed";
2482
+ case "rejected":
2483
+ case "expired":
2484
+ return "error";
2485
+ default:
2486
+ return "queued";
2487
+ }
2488
+ }
2489
+ /**
2490
+ * Normalize Speechmatics response to unified format
2491
+ */
2492
+ normalizeResponse(response) {
2493
+ const text = response.results.filter((r) => r.type === "word").map((r) => r.alternatives[0]?.content || "").join(" ");
2494
+ const words = response.results.filter((r) => r.type === "word").map((result) => ({
2495
+ text: result.alternatives[0]?.content || "",
2496
+ start: result.start_time,
2497
+ end: result.end_time,
2498
+ confidence: result.alternatives[0]?.confidence,
2499
+ speaker: result.alternatives[0]?.speaker
2500
+ }));
2501
+ const speakerSet = /* @__PURE__ */ new Set();
2502
+ response.results.forEach((r) => {
2503
+ const speaker = r.alternatives[0]?.speaker;
2504
+ if (speaker) speakerSet.add(speaker);
2505
+ });
2506
+ const speakers = speakerSet.size > 0 ? Array.from(speakerSet).map((id) => ({
2507
+ id,
2508
+ label: `Speaker ${id}`
2509
+ })) : void 0;
2510
+ const utterances = [];
2511
+ if (speakers) {
2512
+ let currentSpeaker;
2513
+ let currentUtterance = [];
2514
+ let utteranceStart = 0;
2515
+ response.results.filter((r) => r.type === "word").forEach((result, idx) => {
2516
+ const speaker = result.alternatives[0]?.speaker;
2517
+ const word = result.alternatives[0]?.content || "";
2518
+ if (speaker !== currentSpeaker) {
2519
+ if (currentSpeaker && currentUtterance.length > 0) {
2520
+ const prevResult = response.results.filter((r) => r.type === "word")[idx - 1];
2521
+ utterances.push({
2522
+ speaker: currentSpeaker,
2523
+ text: currentUtterance.join(" "),
2524
+ start: utteranceStart,
2525
+ end: prevResult?.end_time || result.start_time
2526
+ });
2527
+ }
2528
+ currentSpeaker = speaker;
2529
+ currentUtterance = [word];
2530
+ utteranceStart = result.start_time;
2531
+ } else {
2532
+ currentUtterance.push(word);
2533
+ }
2534
+ });
2535
+ if (currentSpeaker && currentUtterance.length > 0) {
2536
+ const lastWord = response.results.filter((r) => r.type === "word").pop();
2537
+ utterances.push({
2538
+ speaker: currentSpeaker,
2539
+ text: currentUtterance.join(" "),
2540
+ start: utteranceStart,
2541
+ end: lastWord?.end_time || utteranceStart
2542
+ });
2543
+ }
2544
+ }
2545
+ return {
2546
+ success: true,
2547
+ provider: this.name,
2548
+ data: {
2549
+ id: response.job.id,
2550
+ text,
2551
+ status: "completed",
2552
+ language: response.metadata.transcription_config.language,
2553
+ duration: response.job.duration,
2554
+ speakers,
2555
+ words: words.length > 0 ? words : void 0,
2556
+ utterances: utterances.length > 0 ? utterances : void 0,
2557
+ summary: response.summary?.content,
2558
+ createdAt: response.job.created_at
2559
+ },
2560
+ raw: response
2561
+ };
2562
+ }
2563
+ };
2564
+ function createSpeechmaticsAdapter(config) {
2565
+ const adapter = new SpeechmaticsAdapter();
2566
+ adapter.initialize(config);
2567
+ return adapter;
2568
+ }
2569
+
2570
+ // src/webhooks/base-webhook.ts
2571
+ var BaseWebhookHandler = class {
2572
+ /**
2573
+ * Validate webhook payload structure
2574
+ *
2575
+ * Checks if payload has required fields and correct types
2576
+ *
2577
+ * @param payload - Raw webhook payload
2578
+ * @param options - Optional context (query params, headers, etc.)
2579
+ * @returns Validation result with details
2580
+ */
2581
+ validate(payload, options) {
2582
+ try {
2583
+ if (!this.matches(payload, options)) {
2584
+ return {
2585
+ valid: false,
2586
+ error: `Payload does not match ${this.provider} webhook format`
2587
+ };
2588
+ }
2589
+ const event = this.parse(payload, options);
2590
+ if (!event.provider || !event.eventType) {
2591
+ return {
2592
+ valid: false,
2593
+ error: "Parsed event missing required fields"
2594
+ };
2595
+ }
2596
+ return {
2597
+ valid: true,
2598
+ provider: this.provider,
2599
+ details: {
2600
+ eventType: event.eventType,
2601
+ success: event.success
2602
+ }
2603
+ };
2604
+ } catch (error) {
2605
+ return {
2606
+ valid: false,
2607
+ error: error instanceof Error ? error.message : "Unknown error",
2608
+ details: { error }
2609
+ };
2610
+ }
2611
+ }
2612
+ /**
2613
+ * Helper method to create error response
2614
+ */
2615
+ createErrorEvent(payload, errorMessage) {
2616
+ return {
2617
+ success: false,
2618
+ provider: this.provider,
2619
+ eventType: "transcription.failed",
2620
+ data: {
2621
+ id: "",
2622
+ status: "error",
2623
+ error: errorMessage
2624
+ },
2625
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2626
+ raw: payload
2627
+ };
2628
+ }
2629
+ };
2630
+
2631
+ // src/webhooks/gladia-webhook.ts
2632
+ var GladiaWebhookHandler = class extends BaseWebhookHandler {
2633
+ constructor() {
2634
+ super(...arguments);
2635
+ this.provider = "gladia";
2636
+ }
2637
+ /**
2638
+ * Check if payload matches Gladia webhook format
2639
+ */
2640
+ matches(payload, _options) {
2641
+ if (!payload || typeof payload !== "object") {
2642
+ return false;
2643
+ }
2644
+ const obj = payload;
2645
+ if (!("event" in obj) || !("payload" in obj)) {
2646
+ return false;
2647
+ }
2648
+ if (typeof obj.event !== "string") {
2649
+ return false;
2650
+ }
2651
+ if (!obj.event.startsWith("transcription.")) {
2652
+ return false;
2653
+ }
2654
+ if (!obj.payload || typeof obj.payload !== "object") {
2655
+ return false;
2656
+ }
2657
+ const payloadObj = obj.payload;
2658
+ return typeof payloadObj.id === "string";
2659
+ }
2660
+ /**
2661
+ * Parse Gladia webhook payload to unified format
2662
+ */
2663
+ parse(payload, _options) {
2664
+ if (!this.matches(payload)) {
2665
+ return this.createErrorEvent(payload, "Invalid Gladia webhook payload");
2666
+ }
2667
+ const webhookPayload = payload;
2668
+ const jobId = webhookPayload.payload.id;
2669
+ const event = webhookPayload.event;
2670
+ if (event === "transcription.created") {
2671
+ return {
2672
+ success: true,
2673
+ provider: this.provider,
2674
+ eventType: "transcription.created",
2675
+ data: {
2676
+ id: jobId,
2677
+ status: "queued"
2678
+ },
2679
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2680
+ raw: payload
2681
+ };
2682
+ }
2683
+ if (event === "transcription.success") {
2684
+ return {
2685
+ success: true,
2686
+ provider: this.provider,
2687
+ eventType: "transcription.completed",
2688
+ data: {
2689
+ id: jobId,
2690
+ status: "completed"
2691
+ // Note: Full transcript data needs to be fetched via API
2692
+ // using GladiaAdapter.getTranscript(jobId)
2693
+ },
2694
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2695
+ raw: payload
2696
+ };
2697
+ }
2698
+ if (event === "transcription.error") {
2699
+ return {
2700
+ success: false,
2701
+ provider: this.provider,
2702
+ eventType: "transcription.failed",
2703
+ data: {
2704
+ id: jobId,
2705
+ status: "error",
2706
+ error: "Transcription failed"
2707
+ },
2708
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2709
+ raw: payload
2710
+ };
2711
+ }
2712
+ return this.createErrorEvent(payload, `Unknown Gladia webhook event: ${event}`);
2713
+ }
2714
+ /**
2715
+ * Verify Gladia webhook signature
2716
+ *
2717
+ * Note: As of the current API version, Gladia does not provide
2718
+ * webhook signature verification. This method is a placeholder
2719
+ * for future implementation.
2720
+ *
2721
+ * @param payload - Webhook payload
2722
+ * @param options - Verification options
2723
+ * @returns Always returns true (no verification available)
2724
+ */
2725
+ verify() {
2726
+ return true;
2727
+ }
2728
+ };
2729
+ function createGladiaWebhookHandler() {
2730
+ return new GladiaWebhookHandler();
2731
+ }
2732
+
2733
+ // src/webhooks/assemblyai-webhook.ts
2734
+ var import_node_crypto = __toESM(require("crypto"));
2735
+ var AssemblyAIWebhookHandler = class extends BaseWebhookHandler {
2736
+ constructor() {
2737
+ super(...arguments);
2738
+ this.provider = "assemblyai";
2739
+ }
2740
+ /**
2741
+ * Check if payload matches AssemblyAI webhook format
2742
+ */
2743
+ matches(payload, _options) {
2744
+ if (!payload || typeof payload !== "object") {
2745
+ return false;
2746
+ }
2747
+ const obj = payload;
2748
+ if (!("transcript_id" in obj) || !("status" in obj)) {
2749
+ return false;
2750
+ }
2751
+ if (typeof obj.transcript_id !== "string") {
2752
+ return false;
2753
+ }
2754
+ if (obj.status !== "completed" && obj.status !== "error") {
2755
+ return false;
2756
+ }
2757
+ return true;
2758
+ }
2759
+ /**
2760
+ * Parse AssemblyAI webhook payload to unified format
2761
+ */
2762
+ parse(payload, _options) {
2763
+ if (!this.matches(payload)) {
2764
+ return this.createErrorEvent(payload, "Invalid AssemblyAI webhook payload");
2765
+ }
2766
+ const notification = payload;
2767
+ const transcriptId = notification.transcript_id;
2768
+ const status = notification.status;
2769
+ if (status === "completed") {
2770
+ return {
2771
+ success: true,
2772
+ provider: this.provider,
2773
+ eventType: "transcription.completed",
2774
+ data: {
2775
+ id: transcriptId,
2776
+ status: "completed"
2777
+ // Note: Full transcript data needs to be fetched via API
2778
+ // using AssemblyAIAdapter.getTranscript(transcriptId)
2779
+ },
2780
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2781
+ raw: payload
2782
+ };
2783
+ }
2784
+ if (status === "error") {
2785
+ return {
2786
+ success: false,
2787
+ provider: this.provider,
2788
+ eventType: "transcription.failed",
2789
+ data: {
2790
+ id: transcriptId,
2791
+ status: "error",
2792
+ error: "Transcription failed"
2793
+ },
2794
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2795
+ raw: payload
2796
+ };
2797
+ }
2798
+ return this.createErrorEvent(payload, `Unknown AssemblyAI status: ${status}`);
2799
+ }
2800
+ /**
2801
+ * Verify AssemblyAI webhook signature
2802
+ *
2803
+ * AssemblyAI uses HMAC-SHA256 for webhook signature verification.
2804
+ * The signature is sent in the X-AssemblyAI-Signature header.
2805
+ *
2806
+ * @param payload - Webhook payload
2807
+ * @param options - Verification options with signature and secret
2808
+ * @returns true if signature is valid
2809
+ *
2810
+ * @example
2811
+ * ```typescript
2812
+ * const isValid = handler.verify(req.body, {
2813
+ * signature: req.headers['x-assemblyai-signature'],
2814
+ * secret: process.env.ASSEMBLYAI_WEBHOOK_SECRET,
2815
+ * rawBody: req.rawBody // Raw request body as string or Buffer
2816
+ * });
2817
+ * ```
2818
+ */
2819
+ verify(payload, options) {
2820
+ if (!options.signature || !options.secret) {
2821
+ return false;
2822
+ }
2823
+ try {
2824
+ const body = options.rawBody || (typeof payload === "string" ? payload : JSON.stringify(payload));
2825
+ const hmac = import_node_crypto.default.createHmac("sha256", options.secret);
2826
+ const bodyBuffer = typeof body === "string" ? Buffer.from(body) : body;
2827
+ hmac.update(bodyBuffer);
2828
+ const computedSignature = hmac.digest("hex");
2829
+ return import_node_crypto.default.timingSafeEqual(Buffer.from(options.signature), Buffer.from(computedSignature));
2830
+ } catch (error) {
2831
+ return false;
2832
+ }
2833
+ }
2834
+ };
2835
+ function createAssemblyAIWebhookHandler() {
2836
+ return new AssemblyAIWebhookHandler();
2837
+ }
2838
+
2839
+ // src/webhooks/deepgram-webhook.ts
2840
+ var DeepgramWebhookHandler = class extends BaseWebhookHandler {
2841
+ constructor() {
2842
+ super(...arguments);
2843
+ this.provider = "deepgram";
2844
+ }
2845
+ /**
2846
+ * Check if payload matches Deepgram webhook format
2847
+ */
2848
+ matches(payload, _options) {
2849
+ if (!payload || typeof payload !== "object") {
2850
+ return false;
2851
+ }
2852
+ const obj = payload;
2853
+ if (!("metadata" in obj) || !("results" in obj)) {
2854
+ return false;
2855
+ }
2856
+ if (!obj.metadata || typeof obj.metadata !== "object") {
2857
+ return false;
2858
+ }
2859
+ const metadata = obj.metadata;
2860
+ if (!("request_id" in metadata)) {
2861
+ return false;
2862
+ }
2863
+ if (!obj.results || typeof obj.results !== "object") {
2864
+ return false;
2865
+ }
2866
+ const results = obj.results;
2867
+ return "channels" in results;
2868
+ }
2869
+ /**
2870
+ * Parse Deepgram webhook payload to unified format
2871
+ */
2872
+ parse(payload, _options) {
2873
+ if (!this.matches(payload)) {
2874
+ return this.createErrorEvent(payload, "Invalid Deepgram webhook payload");
2875
+ }
2876
+ const response = payload;
2877
+ try {
2878
+ const requestId = response.metadata.request_id;
2879
+ const duration = response.metadata.duration;
2880
+ const channels = response.results.channels || [];
2881
+ if (channels.length === 0) {
2882
+ return {
2883
+ success: false,
2884
+ provider: this.provider,
2885
+ eventType: "transcription.failed",
2886
+ data: {
2887
+ id: requestId || "",
2888
+ status: "error",
2889
+ error: "No channels in response"
2890
+ },
2891
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2892
+ raw: payload
2893
+ };
2894
+ }
2895
+ const channel = channels[0];
2896
+ const alternatives = channel.alternatives || [];
2897
+ if (alternatives.length === 0) {
2898
+ return {
2899
+ success: false,
2900
+ provider: this.provider,
2901
+ eventType: "transcription.failed",
2902
+ data: {
2903
+ id: requestId || "",
2904
+ status: "error",
2905
+ error: "No alternatives in response"
2906
+ },
2907
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2908
+ raw: payload
2909
+ };
2910
+ }
2911
+ const alternative = alternatives[0];
2912
+ const transcript = alternative.transcript;
2913
+ if (!transcript) {
2914
+ return {
2915
+ success: false,
2916
+ provider: this.provider,
2917
+ eventType: "transcription.failed",
2918
+ data: {
2919
+ id: requestId || "",
2920
+ status: "error",
2921
+ error: "Empty transcript"
2922
+ },
2923
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2924
+ raw: payload
2925
+ };
2926
+ }
2927
+ const words = alternative.words && alternative.words.length > 0 ? alternative.words.map((word) => ({
2928
+ text: word.word || "",
2929
+ start: word.start || 0,
2930
+ end: word.end || 0,
2931
+ confidence: word.confidence
2932
+ })) : void 0;
2933
+ const speakers = response.results.utterances && response.results.utterances.length > 0 ? response.results.utterances.map((utterance) => ({
2934
+ id: utterance.speaker?.toString() || "unknown",
2935
+ speaker: utterance.speaker?.toString() || "unknown",
2936
+ text: utterance.transcript || "",
2937
+ confidence: utterance.confidence
2938
+ })) : void 0;
2939
+ const utterances = response.results.utterances && response.results.utterances.length > 0 ? response.results.utterances.map((utterance) => ({
2940
+ text: utterance.transcript || "",
2941
+ start: utterance.start || 0,
2942
+ end: utterance.end || 0,
2943
+ speaker: utterance.speaker?.toString(),
2944
+ confidence: utterance.confidence,
2945
+ words: utterance.words && utterance.words.length > 0 ? utterance.words.map((word) => ({
2946
+ text: word.word || "",
2947
+ start: word.start || 0,
2948
+ end: word.end || 0,
2949
+ confidence: word.confidence
2950
+ })) : void 0
2951
+ })) : void 0;
2952
+ const summary = alternative.summaries?.[0]?.summary;
2953
+ return {
2954
+ success: true,
2955
+ provider: this.provider,
2956
+ eventType: "transcription.completed",
2957
+ data: {
2958
+ id: requestId || "",
2959
+ status: "completed",
2960
+ text: transcript,
2961
+ confidence: alternative.confidence,
2962
+ duration,
2963
+ language: response.metadata.models?.[0] || void 0,
2964
+ speakers: speakers && speakers.length > 0 ? speakers : void 0,
2965
+ words: words && words.length > 0 ? words : void 0,
2966
+ utterances: utterances && utterances.length > 0 ? utterances : void 0,
2967
+ summary,
2968
+ metadata: {
2969
+ channels: response.metadata.channels,
2970
+ created: response.metadata.created,
2971
+ models: response.metadata.models
2972
+ }
2973
+ },
2974
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2975
+ raw: payload
2976
+ };
2977
+ } catch (error) {
2978
+ return this.createErrorEvent(
2979
+ payload,
2980
+ `Failed to parse Deepgram webhook: ${error instanceof Error ? error.message : "Unknown error"}`
2981
+ );
2982
+ }
2983
+ }
2984
+ /**
2985
+ * Verify Deepgram webhook signature
2986
+ *
2987
+ * Note: Deepgram does not currently support webhook signature verification.
2988
+ * For security, use HTTPS and validate the request source (IP allowlist, etc.).
2989
+ *
2990
+ * @returns Always returns true (no verification available)
2991
+ */
2992
+ verify() {
2993
+ return true;
2994
+ }
2995
+ };
2996
+ function createDeepgramWebhookHandler() {
2997
+ return new DeepgramWebhookHandler();
2998
+ }
2999
+
3000
+ // src/webhooks/azure-webhook.ts
3001
+ var import_node_crypto2 = __toESM(require("crypto"));
3002
+ var AzureWebhookHandler = class extends BaseWebhookHandler {
3003
+ constructor() {
3004
+ super(...arguments);
3005
+ this.provider = "azure-stt";
3006
+ }
3007
+ /**
3008
+ * Check if payload matches Azure webhook format
3009
+ */
3010
+ matches(payload, _options) {
3011
+ if (!payload || typeof payload !== "object") {
3012
+ return false;
3013
+ }
3014
+ const obj = payload;
3015
+ if (!("action" in obj) || !("timestamp" in obj)) {
3016
+ return false;
3017
+ }
3018
+ if (typeof obj.action !== "string") {
3019
+ return false;
3020
+ }
3021
+ if (!obj.action.startsWith("Transcription")) {
3022
+ return false;
3023
+ }
3024
+ return true;
3025
+ }
3026
+ /**
3027
+ * Parse Azure webhook payload to unified format
3028
+ */
3029
+ parse(payload, _options) {
3030
+ if (!this.matches(payload)) {
3031
+ return this.createErrorEvent(payload, "Invalid Azure webhook payload");
3032
+ }
3033
+ const webhookPayload = payload;
3034
+ const action = webhookPayload.action;
3035
+ const timestamp = webhookPayload.timestamp;
3036
+ let transcriptionId = "";
3037
+ if (webhookPayload.self) {
3038
+ const match = webhookPayload.self.match(/\/transcriptions\/([^/?]+)/);
3039
+ if (match) {
3040
+ transcriptionId = match[1];
3041
+ }
3042
+ }
3043
+ if (action === "TranscriptionCreated") {
3044
+ return {
3045
+ success: true,
3046
+ provider: this.provider,
3047
+ eventType: "transcription.created",
3048
+ data: {
3049
+ id: transcriptionId,
3050
+ status: "queued",
3051
+ createdAt: timestamp
3052
+ },
3053
+ timestamp,
3054
+ raw: payload
3055
+ };
3056
+ }
3057
+ if (action === "TranscriptionRunning") {
3058
+ return {
3059
+ success: true,
3060
+ provider: this.provider,
3061
+ eventType: "transcription.processing",
3062
+ data: {
3063
+ id: transcriptionId,
3064
+ status: "processing"
3065
+ },
3066
+ timestamp,
3067
+ raw: payload
3068
+ };
3069
+ }
3070
+ if (action === "TranscriptionSucceeded") {
3071
+ return {
3072
+ success: true,
3073
+ provider: this.provider,
3074
+ eventType: "transcription.completed",
3075
+ data: {
3076
+ id: transcriptionId,
3077
+ status: "completed",
3078
+ completedAt: timestamp
3079
+ // Note: Full transcript data needs to be fetched via API
3080
+ // using AzureAdapter.getTranscript(transcriptionId)
3081
+ },
3082
+ timestamp,
3083
+ raw: payload
3084
+ };
3085
+ }
3086
+ if (action === "TranscriptionFailed") {
3087
+ return {
3088
+ success: false,
3089
+ provider: this.provider,
3090
+ eventType: "transcription.failed",
3091
+ data: {
3092
+ id: transcriptionId,
3093
+ status: "error",
3094
+ error: webhookPayload.error?.message || "Transcription failed",
3095
+ metadata: {
3096
+ errorCode: webhookPayload.error?.code
3097
+ }
3098
+ },
3099
+ timestamp,
3100
+ raw: payload
3101
+ };
3102
+ }
3103
+ return this.createErrorEvent(payload, `Unknown Azure webhook action: ${action}`);
3104
+ }
3105
+ /**
3106
+ * Verify Azure webhook signature
3107
+ *
3108
+ * Azure can optionally sign webhooks using HMAC-SHA256.
3109
+ * The signature is sent in the X-Azure-Signature header.
3110
+ *
3111
+ * Note: Signature verification is optional in Azure and must be
3112
+ * configured when creating the webhook.
3113
+ *
3114
+ * @param payload - Webhook payload
3115
+ * @param options - Verification options with signature and secret
3116
+ * @returns true if signature is valid or no signature provided
3117
+ *
3118
+ * @example
3119
+ * ```typescript
3120
+ * const isValid = handler.verify(req.body, {
3121
+ * signature: req.headers['x-azure-signature'],
3122
+ * secret: process.env.AZURE_WEBHOOK_SECRET,
3123
+ * rawBody: req.rawBody
3124
+ * });
3125
+ * ```
3126
+ */
3127
+ verify(payload, options) {
3128
+ if (!options.signature) {
3129
+ return true;
3130
+ }
3131
+ if (!options.secret) {
3132
+ return false;
3133
+ }
3134
+ try {
3135
+ const body = options.rawBody || (typeof payload === "string" ? payload : JSON.stringify(payload));
3136
+ const hmac = import_node_crypto2.default.createHmac("sha256", options.secret);
3137
+ const bodyBuffer = typeof body === "string" ? Buffer.from(body) : body;
3138
+ hmac.update(bodyBuffer);
3139
+ const computedSignature = hmac.digest("hex");
3140
+ return import_node_crypto2.default.timingSafeEqual(Buffer.from(options.signature), Buffer.from(computedSignature));
3141
+ } catch (error) {
3142
+ return false;
3143
+ }
3144
+ }
3145
+ };
3146
+ function createAzureWebhookHandler() {
3147
+ return new AzureWebhookHandler();
3148
+ }
3149
+
3150
+ // src/webhooks/speechmatics-webhook.ts
3151
+ var SpeechmaticsWebhookHandler = class extends BaseWebhookHandler {
3152
+ constructor() {
3153
+ super(...arguments);
3154
+ this.provider = "speechmatics";
3155
+ }
3156
+ /**
3157
+ * Check if payload matches Speechmatics webhook format
3158
+ */
3159
+ matches(payload, options) {
3160
+ if (options?.userAgent) {
3161
+ if (!options.userAgent.includes("Speechmatics-API")) {
3162
+ return false;
3163
+ }
3164
+ }
3165
+ if (options?.queryParams) {
3166
+ const { id, status } = options.queryParams;
3167
+ if (!id || !status) {
3168
+ return false;
3169
+ }
3170
+ }
3171
+ if (payload && typeof payload === "object") {
3172
+ const obj = payload;
3173
+ if ("format" in obj && "job" in obj && "metadata" in obj) {
3174
+ return true;
3175
+ }
3176
+ if ("job" in obj || "id" in obj) {
3177
+ return true;
3178
+ }
3179
+ }
3180
+ return !!options?.queryParams?.id && !!options?.queryParams?.status;
3181
+ }
3182
+ /**
3183
+ * Validate webhook request
3184
+ */
3185
+ validate(payload, options) {
3186
+ if (!options?.queryParams?.id) {
3187
+ return {
3188
+ valid: false,
3189
+ error: "Missing required query parameter: id"
3190
+ };
3191
+ }
3192
+ if (!options?.queryParams?.status) {
3193
+ return {
3194
+ valid: false,
3195
+ error: "Missing required query parameter: status"
3196
+ };
3197
+ }
3198
+ const validStatuses = ["success", "error", "fetch_error", "trim_error"];
3199
+ if (!validStatuses.includes(options.queryParams.status)) {
3200
+ return {
3201
+ valid: false,
3202
+ error: `Invalid status value: ${options.queryParams.status}`
3203
+ };
3204
+ }
3205
+ if (options?.userAgent && !options.userAgent.includes("Speechmatics-API")) {
3206
+ return {
3207
+ valid: false,
3208
+ error: "Invalid user agent (expected Speechmatics-API/2.0)"
3209
+ };
3210
+ }
3211
+ return { valid: true };
3212
+ }
3213
+ /**
3214
+ * Parse webhook payload into unified event format
3215
+ */
3216
+ parse(payload, options) {
3217
+ const queryParams = options?.queryParams || {};
3218
+ const jobId = queryParams.id;
3219
+ const status = queryParams.status;
3220
+ let eventType;
3221
+ if (status === "success") {
3222
+ eventType = "transcription.completed";
3223
+ } else if (status === "error" || status === "fetch_error" || status === "trim_error") {
3224
+ eventType = "transcription.failed";
3225
+ } else {
3226
+ eventType = "transcription.created";
3227
+ }
3228
+ if (status === "success" && payload && typeof payload === "object") {
3229
+ const transcript = payload;
3230
+ if (transcript.results && transcript.job) {
3231
+ const text = transcript.results.filter((r) => r.type === "word").map((r) => r.alternatives[0]?.content || "").join(" ");
3232
+ const speakerSet = /* @__PURE__ */ new Set();
3233
+ transcript.results.forEach((r) => {
3234
+ const speaker = r.alternatives[0]?.speaker;
3235
+ if (speaker) speakerSet.add(speaker);
3236
+ });
3237
+ const speakers = speakerSet.size > 0 ? Array.from(speakerSet).map((id) => ({
3238
+ id,
3239
+ label: `Speaker ${id}`
3240
+ })) : void 0;
3241
+ return {
3242
+ success: true,
3243
+ provider: this.provider,
3244
+ eventType,
3245
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3246
+ data: {
3247
+ id: jobId,
3248
+ text,
3249
+ status: "completed",
3250
+ language: transcript.metadata.transcription_config.language,
3251
+ duration: transcript.job.duration,
3252
+ speakers,
3253
+ createdAt: transcript.job.created_at
3254
+ },
3255
+ raw: payload
3256
+ };
3257
+ }
3258
+ }
3259
+ return {
3260
+ success: status === "success",
3261
+ provider: this.provider,
3262
+ eventType,
3263
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3264
+ data: {
3265
+ id: jobId,
3266
+ text: "",
3267
+ status: status === "success" ? "completed" : "error"
3268
+ },
3269
+ raw: payload
3270
+ };
3271
+ }
3272
+ };
3273
+
3274
+ // src/webhooks/webhook-router.ts
3275
+ var WebhookRouter = class {
3276
+ constructor() {
3277
+ this.handlers = /* @__PURE__ */ new Map([
3278
+ ["gladia", new GladiaWebhookHandler()],
3279
+ ["assemblyai", new AssemblyAIWebhookHandler()],
3280
+ ["deepgram", new DeepgramWebhookHandler()],
3281
+ ["azure-stt", new AzureWebhookHandler()],
3282
+ ["speechmatics", new SpeechmaticsWebhookHandler()]
3283
+ ]);
3284
+ }
3285
+ /**
3286
+ * Route webhook payload to the correct handler
3287
+ *
3288
+ * @param payload - Raw webhook payload
3289
+ * @param options - Routing options (provider, verification, etc.)
3290
+ * @returns Routing result with parsed event
3291
+ */
3292
+ route(payload, options) {
3293
+ if (options?.provider) {
3294
+ return this.routeToProvider(payload, options.provider, options);
3295
+ }
3296
+ const detectedProvider = this.detectProvider(payload, {
3297
+ queryParams: options?.queryParams,
3298
+ userAgent: options?.userAgent
3299
+ });
3300
+ if (!detectedProvider) {
3301
+ return {
3302
+ success: false,
3303
+ error: "Could not detect webhook provider from payload structure"
3304
+ };
3305
+ }
3306
+ return this.routeToProvider(payload, detectedProvider, options);
3307
+ }
3308
+ /**
3309
+ * Detect provider from webhook payload structure
3310
+ *
3311
+ * @param payload - Raw webhook payload
3312
+ * @param options - Detection options (query params, user agent, etc.)
3313
+ * @returns Detected provider or undefined
3314
+ */
3315
+ detectProvider(payload, options) {
3316
+ for (const [provider, handler] of this.handlers) {
3317
+ if (handler.matches(payload, options)) {
3318
+ return provider;
3319
+ }
3320
+ }
3321
+ return void 0;
3322
+ }
3323
+ /**
3324
+ * Validate webhook payload
3325
+ *
3326
+ * @param payload - Raw webhook payload
3327
+ * @param options - Routing options
3328
+ * @returns Validation result
3329
+ */
3330
+ validate(payload, options) {
3331
+ if (options?.provider) {
3332
+ const handler2 = this.handlers.get(options.provider);
3333
+ if (!handler2) {
3334
+ return {
3335
+ valid: false,
3336
+ error: `Unknown provider: ${options.provider}`
3337
+ };
3338
+ }
3339
+ return handler2.validate(payload, {
3340
+ queryParams: options.queryParams,
3341
+ userAgent: options.userAgent
3342
+ });
3343
+ }
3344
+ const detectedProvider = this.detectProvider(payload, {
3345
+ queryParams: options?.queryParams,
3346
+ userAgent: options?.userAgent
3347
+ });
3348
+ if (!detectedProvider) {
3349
+ return {
3350
+ valid: false,
3351
+ error: "Could not detect webhook provider from payload structure"
3352
+ };
3353
+ }
3354
+ const handler = this.handlers.get(detectedProvider);
3355
+ if (!handler) {
3356
+ return {
3357
+ valid: false,
3358
+ error: `Handler not found for provider: ${detectedProvider}`
3359
+ };
3360
+ }
3361
+ return handler.validate(payload, {
3362
+ queryParams: options?.queryParams,
3363
+ userAgent: options?.userAgent
3364
+ });
3365
+ }
3366
+ /**
3367
+ * Verify webhook signature
3368
+ *
3369
+ * @param payload - Raw webhook payload
3370
+ * @param provider - Provider name
3371
+ * @param options - Verification options
3372
+ * @returns true if signature is valid
3373
+ */
3374
+ verify(payload, provider, options) {
3375
+ const handler = this.handlers.get(provider);
3376
+ if (!handler || !handler.verify) {
3377
+ return true;
3378
+ }
3379
+ return handler.verify(payload, options);
3380
+ }
3381
+ /**
3382
+ * Route to a specific provider handler
3383
+ */
3384
+ routeToProvider(payload, provider, options) {
3385
+ const handler = this.handlers.get(provider);
3386
+ if (!handler) {
3387
+ return {
3388
+ success: false,
3389
+ error: `Handler not found for provider: ${provider}`
3390
+ };
3391
+ }
3392
+ let verified = true;
3393
+ if (options?.verifySignature !== false && options?.verification && handler.verify) {
3394
+ verified = handler.verify(payload, options.verification);
3395
+ if (!verified) {
3396
+ return {
3397
+ success: false,
3398
+ provider,
3399
+ error: "Webhook signature verification failed",
3400
+ verified: false
3401
+ };
3402
+ }
3403
+ }
3404
+ const validation = handler.validate(payload, {
3405
+ queryParams: options?.queryParams,
3406
+ userAgent: options?.userAgent
3407
+ });
3408
+ if (!validation.valid) {
3409
+ return {
3410
+ success: false,
3411
+ provider,
3412
+ error: validation.error,
3413
+ verified
3414
+ };
3415
+ }
3416
+ try {
3417
+ const event = handler.parse(payload, {
3418
+ queryParams: options?.queryParams
3419
+ });
3420
+ return {
3421
+ success: true,
3422
+ provider,
3423
+ event,
3424
+ verified
3425
+ };
3426
+ } catch (error) {
3427
+ return {
3428
+ success: false,
3429
+ provider,
3430
+ error: `Failed to parse webhook: ${error instanceof Error ? error.message : "Unknown error"}`,
3431
+ verified
3432
+ };
3433
+ }
3434
+ }
3435
+ /**
3436
+ * Get handler for a specific provider
3437
+ *
3438
+ * @param provider - Provider name
3439
+ * @returns Handler instance or undefined
3440
+ */
3441
+ getHandler(provider) {
3442
+ return this.handlers.get(provider);
3443
+ }
3444
+ /**
3445
+ * Get all registered providers
3446
+ *
3447
+ * @returns Array of provider names
3448
+ */
3449
+ getProviders() {
3450
+ return Array.from(this.handlers.keys());
3451
+ }
3452
+ };
3453
+ function createWebhookRouter() {
3454
+ return new WebhookRouter();
3455
+ }
3456
+
3457
+ // src/generated/gladia/schema/index.ts
3458
+ var schema_exports = {};
3459
+ __export(schema_exports, {
3460
+ AudioChunkAckMessageType: () => AudioChunkAckMessageType,
3461
+ AudioChunkActionType: () => AudioChunkActionType,
3462
+ AudioToTextControllerAudioTranscriptionBodyLanguage: () => AudioToTextControllerAudioTranscriptionBodyLanguage,
3463
+ AudioToTextControllerAudioTranscriptionBodyLanguageBehaviour: () => AudioToTextControllerAudioTranscriptionBodyLanguageBehaviour,
3464
+ AudioToTextControllerAudioTranscriptionBodyOutputFormat: () => AudioToTextControllerAudioTranscriptionBodyOutputFormat,
3465
+ AudioToTextControllerAudioTranscriptionBodyTargetTranslationLanguage: () => AudioToTextControllerAudioTranscriptionBodyTargetTranslationLanguage,
3466
+ CallbackLiveAudioChunkAckMessageEvent: () => CallbackLiveAudioChunkAckMessageEvent,
3467
+ CallbackLiveEndRecordingMessageEvent: () => CallbackLiveEndRecordingMessageEvent,
3468
+ CallbackLiveEndSessionMessageEvent: () => CallbackLiveEndSessionMessageEvent,
3469
+ CallbackLiveNamedEntityRecognitionMessageEvent: () => CallbackLiveNamedEntityRecognitionMessageEvent,
3470
+ CallbackLivePostChapterizationMessageEvent: () => CallbackLivePostChapterizationMessageEvent,
3471
+ CallbackLivePostFinalTranscriptMessageEvent: () => CallbackLivePostFinalTranscriptMessageEvent,
3472
+ CallbackLivePostSummarizationMessageEvent: () => CallbackLivePostSummarizationMessageEvent,
3473
+ CallbackLivePostTranscriptMessageEvent: () => CallbackLivePostTranscriptMessageEvent,
3474
+ CallbackLiveSentimentAnalysisMessageEvent: () => CallbackLiveSentimentAnalysisMessageEvent,
3475
+ CallbackLiveSpeechEndMessageEvent: () => CallbackLiveSpeechEndMessageEvent,
3476
+ CallbackLiveSpeechStartMessageEvent: () => CallbackLiveSpeechStartMessageEvent,
3477
+ CallbackLiveStartRecordingMessageEvent: () => CallbackLiveStartRecordingMessageEvent,
3478
+ CallbackLiveStartSessionMessageEvent: () => CallbackLiveStartSessionMessageEvent,
3479
+ CallbackLiveStopRecordingAckMessageEvent: () => CallbackLiveStopRecordingAckMessageEvent,
3480
+ CallbackLiveTranscriptMessageEvent: () => CallbackLiveTranscriptMessageEvent,
3481
+ CallbackLiveTranslationMessageEvent: () => CallbackLiveTranslationMessageEvent,
3482
+ CallbackMethodEnum: () => CallbackMethodEnum,
3483
+ CallbackTranscriptionErrorPayloadEvent: () => CallbackTranscriptionErrorPayloadEvent,
3484
+ CallbackTranscriptionSuccessPayloadEvent: () => CallbackTranscriptionSuccessPayloadEvent,
3485
+ EndRecordingMessageType: () => EndRecordingMessageType,
3486
+ EndSessionMessageType: () => EndSessionMessageType,
3487
+ HistoryControllerGetListV1KindItem: () => HistoryControllerGetListV1KindItem,
3488
+ HistoryControllerGetListV1StatusItem: () => HistoryControllerGetListV1StatusItem,
3489
+ NamedEntityRecognitionMessageType: () => NamedEntityRecognitionMessageType,
3490
+ PostChapterizationMessageType: () => PostChapterizationMessageType,
3491
+ PostFinalTranscriptMessageType: () => PostFinalTranscriptMessageType,
3492
+ PostSummarizationMessageType: () => PostSummarizationMessageType,
3493
+ PostTranscriptMessageType: () => PostTranscriptMessageType,
3494
+ PreRecordedControllerGetPreRecordedJobsV2StatusItem: () => PreRecordedControllerGetPreRecordedJobsV2StatusItem,
3495
+ PreRecordedResponseKind: () => PreRecordedResponseKind,
3496
+ PreRecordedResponseStatus: () => PreRecordedResponseStatus,
3497
+ SentimentAnalysisMessageType: () => SentimentAnalysisMessageType,
3498
+ SpeechEndMessageType: () => SpeechEndMessageType,
3499
+ SpeechStartMessageType: () => SpeechStartMessageType,
3500
+ StartRecordingMessageType: () => StartRecordingMessageType,
3501
+ StartSessionMessageType: () => StartSessionMessageType,
3502
+ StopRecordingAckMessageType: () => StopRecordingAckMessageType,
3503
+ StopRecordingActionType: () => StopRecordingActionType,
3504
+ StreamingControllerGetStreamingJobsV2StatusItem: () => StreamingControllerGetStreamingJobsV2StatusItem,
3505
+ StreamingResponseKind: () => StreamingResponseKind,
3506
+ StreamingResponseStatus: () => StreamingResponseStatus,
3507
+ StreamingSupportedBitDepthEnum: () => StreamingSupportedBitDepthEnum,
3508
+ StreamingSupportedEncodingEnum: () => StreamingSupportedEncodingEnum,
3509
+ StreamingSupportedModels: () => StreamingSupportedModels,
3510
+ StreamingSupportedRegions: () => StreamingSupportedRegions,
3511
+ StreamingSupportedSampleRateEnum: () => StreamingSupportedSampleRateEnum,
3512
+ SubtitlesFormatEnum: () => SubtitlesFormatEnum,
3513
+ SubtitlesStyleEnum: () => SubtitlesStyleEnum,
3514
+ SummaryTypesEnum: () => SummaryTypesEnum,
3515
+ TranscriptMessageType: () => TranscriptMessageType,
3516
+ TranscriptionControllerListV2KindItem: () => TranscriptionControllerListV2KindItem,
3517
+ TranscriptionControllerListV2StatusItem: () => TranscriptionControllerListV2StatusItem,
3518
+ TranscriptionLanguageCodeEnum: () => TranscriptionLanguageCodeEnum,
3519
+ TranslationLanguageCodeEnum: () => TranslationLanguageCodeEnum,
3520
+ TranslationMessageType: () => TranslationMessageType,
3521
+ TranslationModelEnum: () => TranslationModelEnum,
3522
+ VideoToTextControllerVideoTranscriptionBodyLanguage: () => VideoToTextControllerVideoTranscriptionBodyLanguage,
3523
+ VideoToTextControllerVideoTranscriptionBodyLanguageBehaviour: () => VideoToTextControllerVideoTranscriptionBodyLanguageBehaviour,
3524
+ VideoToTextControllerVideoTranscriptionBodyOutputFormat: () => VideoToTextControllerVideoTranscriptionBodyOutputFormat,
3525
+ VideoToTextControllerVideoTranscriptionBodyTargetTranslationLanguage: () => VideoToTextControllerVideoTranscriptionBodyTargetTranslationLanguage,
3526
+ WebhookLiveEndRecordingPayloadEvent: () => WebhookLiveEndRecordingPayloadEvent,
3527
+ WebhookLiveEndSessionPayloadEvent: () => WebhookLiveEndSessionPayloadEvent,
3528
+ WebhookLiveStartRecordingPayloadEvent: () => WebhookLiveStartRecordingPayloadEvent,
3529
+ WebhookLiveStartSessionPayloadEvent: () => WebhookLiveStartSessionPayloadEvent,
3530
+ WebhookTranscriptionCreatedPayloadEvent: () => WebhookTranscriptionCreatedPayloadEvent,
3531
+ WebhookTranscriptionErrorPayloadEvent: () => WebhookTranscriptionErrorPayloadEvent,
3532
+ WebhookTranscriptionSuccessPayloadEvent: () => WebhookTranscriptionSuccessPayloadEvent
3533
+ });
3534
+
3535
+ // src/generated/gladia/schema/audioChunkAckMessageType.ts
3536
+ var AudioChunkAckMessageType = {
3537
+ audio_chunk: "audio_chunk"
3538
+ };
3539
+
3540
+ // src/generated/gladia/schema/audioChunkActionType.ts
3541
+ var AudioChunkActionType = {
3542
+ audio_chunk: "audio_chunk"
3543
+ };
3544
+
3545
+ // src/generated/gladia/schema/audioToTextControllerAudioTranscriptionBodyLanguage.ts
3546
+ var AudioToTextControllerAudioTranscriptionBodyLanguage = {
3547
+ afrikaans: "afrikaans",
3548
+ albanian: "albanian",
3549
+ amharic: "amharic",
3550
+ arabic: "arabic",
3551
+ armenian: "armenian",
3552
+ assamese: "assamese",
3553
+ azerbaijani: "azerbaijani",
3554
+ bashkir: "bashkir",
3555
+ basque: "basque",
3556
+ belarusian: "belarusian",
3557
+ bengali: "bengali",
3558
+ bosnian: "bosnian",
3559
+ breton: "breton",
3560
+ bulgarian: "bulgarian",
3561
+ catalan: "catalan",
3562
+ chinese: "chinese",
3563
+ croatian: "croatian",
3564
+ czech: "czech",
3565
+ danish: "danish",
3566
+ dutch: "dutch",
3567
+ english: "english",
3568
+ estonian: "estonian",
3569
+ faroese: "faroese",
3570
+ finnish: "finnish",
3571
+ french: "french",
3572
+ galician: "galician",
3573
+ georgian: "georgian",
3574
+ german: "german",
3575
+ greek: "greek",
3576
+ gujarati: "gujarati",
3577
+ haitian_creole: "haitian creole",
3578
+ hausa: "hausa",
3579
+ hawaiian: "hawaiian",
3580
+ hebrew: "hebrew",
3581
+ hindi: "hindi",
3582
+ hungarian: "hungarian",
3583
+ icelandic: "icelandic",
3584
+ indonesian: "indonesian",
3585
+ italian: "italian",
3586
+ japanese: "japanese",
3587
+ javanese: "javanese",
3588
+ kannada: "kannada",
3589
+ kazakh: "kazakh",
3590
+ khmer: "khmer",
3591
+ korean: "korean",
3592
+ lao: "lao",
3593
+ latin: "latin",
3594
+ latvian: "latvian",
3595
+ lingala: "lingala",
3596
+ lithuanian: "lithuanian",
3597
+ luxembourgish: "luxembourgish",
3598
+ macedonian: "macedonian",
3599
+ malagasy: "malagasy",
3600
+ malay: "malay",
3601
+ malayalam: "malayalam",
3602
+ maltese: "maltese",
3603
+ maori: "maori",
3604
+ marathi: "marathi",
3605
+ mongolian: "mongolian",
3606
+ myanmar: "myanmar",
3607
+ nepali: "nepali",
3608
+ norwegian: "norwegian",
3609
+ nynorsk: "nynorsk",
3610
+ occitan: "occitan",
3611
+ pashto: "pashto",
3612
+ persian: "persian",
3613
+ polish: "polish",
3614
+ portuguese: "portuguese",
3615
+ punjabi: "punjabi",
3616
+ romanian: "romanian",
3617
+ russian: "russian",
3618
+ sanskrit: "sanskrit",
3619
+ serbian: "serbian",
3620
+ shona: "shona",
3621
+ sindhi: "sindhi",
3622
+ sinhala: "sinhala",
3623
+ slovak: "slovak",
3624
+ slovenian: "slovenian",
3625
+ somali: "somali",
3626
+ spanish: "spanish",
3627
+ sundanese: "sundanese",
3628
+ swahili: "swahili",
3629
+ swedish: "swedish",
3630
+ tagalog: "tagalog",
3631
+ tajik: "tajik",
3632
+ tamil: "tamil",
3633
+ tatar: "tatar",
3634
+ telugu: "telugu",
3635
+ thai: "thai",
3636
+ tibetan: "tibetan",
3637
+ turkish: "turkish",
3638
+ turkmen: "turkmen",
3639
+ ukrainian: "ukrainian",
3640
+ urdu: "urdu",
3641
+ uzbek: "uzbek",
3642
+ vietnamese: "vietnamese",
3643
+ welsh: "welsh",
3644
+ yiddish: "yiddish",
3645
+ yoruba: "yoruba"
3646
+ };
3647
+
3648
+ // src/generated/gladia/schema/audioToTextControllerAudioTranscriptionBodyLanguageBehaviour.ts
3649
+ var AudioToTextControllerAudioTranscriptionBodyLanguageBehaviour = {
3650
+ automatic_single_language: "automatic single language",
3651
+ automatic_multiple_languages: "automatic multiple languages",
3652
+ manual: "manual"
3653
+ };
3654
+
3655
+ // src/generated/gladia/schema/audioToTextControllerAudioTranscriptionBodyOutputFormat.ts
3656
+ var AudioToTextControllerAudioTranscriptionBodyOutputFormat = {
3657
+ json: "json",
3658
+ srt: "srt",
3659
+ vtt: "vtt",
3660
+ plain: "plain",
3661
+ txt: "txt"
3662
+ };
3663
+
3664
+ // src/generated/gladia/schema/audioToTextControllerAudioTranscriptionBodyTargetTranslationLanguage.ts
3665
+ var AudioToTextControllerAudioTranscriptionBodyTargetTranslationLanguage = {
3666
+ afrikaans: "afrikaans",
3667
+ albanian: "albanian",
3668
+ amharic: "amharic",
3669
+ arabic: "arabic",
3670
+ armenian: "armenian",
3671
+ assamese: "assamese",
3672
+ azerbaijani: "azerbaijani",
3673
+ bashkir: "bashkir",
3674
+ basque: "basque",
3675
+ belarusian: "belarusian",
3676
+ bengali: "bengali",
3677
+ bosnian: "bosnian",
3678
+ breton: "breton",
3679
+ bulgarian: "bulgarian",
3680
+ catalan: "catalan",
3681
+ chinese: "chinese",
3682
+ croatian: "croatian",
3683
+ czech: "czech",
3684
+ danish: "danish",
3685
+ dutch: "dutch",
3686
+ english: "english",
3687
+ estonian: "estonian",
3688
+ faroese: "faroese",
3689
+ finnish: "finnish",
3690
+ french: "french",
3691
+ galician: "galician",
3692
+ georgian: "georgian",
3693
+ german: "german",
3694
+ greek: "greek",
3695
+ gujarati: "gujarati",
3696
+ haitian_creole: "haitian creole",
3697
+ hausa: "hausa",
3698
+ hawaiian: "hawaiian",
3699
+ hebrew: "hebrew",
3700
+ hindi: "hindi",
3701
+ hungarian: "hungarian",
3702
+ icelandic: "icelandic",
3703
+ indonesian: "indonesian",
3704
+ italian: "italian",
3705
+ japanese: "japanese",
3706
+ javanese: "javanese",
3707
+ kannada: "kannada",
3708
+ kazakh: "kazakh",
3709
+ khmer: "khmer",
3710
+ korean: "korean",
3711
+ lao: "lao",
3712
+ latin: "latin",
3713
+ latvian: "latvian",
3714
+ lingala: "lingala",
3715
+ lithuanian: "lithuanian",
3716
+ luxembourgish: "luxembourgish",
3717
+ macedonian: "macedonian",
3718
+ malagasy: "malagasy",
3719
+ malay: "malay",
3720
+ malayalam: "malayalam",
3721
+ maltese: "maltese",
3722
+ maori: "maori",
3723
+ marathi: "marathi",
3724
+ mongolian: "mongolian",
3725
+ myanmar: "myanmar",
3726
+ nepali: "nepali",
3727
+ norwegian: "norwegian",
3728
+ nynorsk: "nynorsk",
3729
+ occitan: "occitan",
3730
+ pashto: "pashto",
3731
+ persian: "persian",
3732
+ polish: "polish",
3733
+ portuguese: "portuguese",
3734
+ punjabi: "punjabi",
3735
+ romanian: "romanian",
3736
+ russian: "russian",
3737
+ sanskrit: "sanskrit",
3738
+ serbian: "serbian",
3739
+ shona: "shona",
3740
+ sindhi: "sindhi",
3741
+ sinhala: "sinhala",
3742
+ slovak: "slovak",
3743
+ slovenian: "slovenian",
3744
+ somali: "somali",
3745
+ spanish: "spanish",
3746
+ sundanese: "sundanese",
3747
+ swahili: "swahili",
3748
+ swedish: "swedish",
3749
+ tagalog: "tagalog",
3750
+ tajik: "tajik",
3751
+ tamil: "tamil",
3752
+ tatar: "tatar",
3753
+ telugu: "telugu",
3754
+ thai: "thai",
3755
+ tibetan: "tibetan",
3756
+ turkish: "turkish",
3757
+ turkmen: "turkmen",
3758
+ ukrainian: "ukrainian",
3759
+ urdu: "urdu",
3760
+ uzbek: "uzbek",
3761
+ vietnamese: "vietnamese",
3762
+ welsh: "welsh",
3763
+ wolof: "wolof",
3764
+ yiddish: "yiddish",
3765
+ yoruba: "yoruba"
3766
+ };
3767
+
3768
+ // src/generated/gladia/schema/callbackLiveAudioChunkAckMessageEvent.ts
3769
+ var CallbackLiveAudioChunkAckMessageEvent = {
3770
+ liveaudio_chunk: "live.audio_chunk"
3771
+ };
3772
+
3773
+ // src/generated/gladia/schema/callbackLiveEndRecordingMessageEvent.ts
3774
+ var CallbackLiveEndRecordingMessageEvent = {
3775
+ liveend_recording: "live.end_recording"
3776
+ };
3777
+
3778
+ // src/generated/gladia/schema/callbackLiveEndSessionMessageEvent.ts
3779
+ var CallbackLiveEndSessionMessageEvent = {
3780
+ liveend_session: "live.end_session"
3781
+ };
3782
+
3783
+ // src/generated/gladia/schema/callbackLiveNamedEntityRecognitionMessageEvent.ts
3784
+ var CallbackLiveNamedEntityRecognitionMessageEvent = {
3785
+ livenamed_entity_recognition: "live.named_entity_recognition"
3786
+ };
3787
+
3788
+ // src/generated/gladia/schema/callbackLivePostChapterizationMessageEvent.ts
3789
+ var CallbackLivePostChapterizationMessageEvent = {
3790
+ livepost_chapterization: "live.post_chapterization"
3791
+ };
3792
+
3793
+ // src/generated/gladia/schema/callbackLivePostFinalTranscriptMessageEvent.ts
3794
+ var CallbackLivePostFinalTranscriptMessageEvent = {
3795
+ livepost_final_transcript: "live.post_final_transcript"
3796
+ };
3797
+
3798
+ // src/generated/gladia/schema/callbackLivePostSummarizationMessageEvent.ts
3799
+ var CallbackLivePostSummarizationMessageEvent = {
3800
+ livepost_summarization: "live.post_summarization"
3801
+ };
3802
+
3803
+ // src/generated/gladia/schema/callbackLivePostTranscriptMessageEvent.ts
3804
+ var CallbackLivePostTranscriptMessageEvent = {
3805
+ livepost_transcript: "live.post_transcript"
3806
+ };
3807
+
3808
+ // src/generated/gladia/schema/callbackLiveSentimentAnalysisMessageEvent.ts
3809
+ var CallbackLiveSentimentAnalysisMessageEvent = {
3810
+ livesentiment_analysis: "live.sentiment_analysis"
3811
+ };
3812
+
3813
+ // src/generated/gladia/schema/callbackLiveSpeechEndMessageEvent.ts
3814
+ var CallbackLiveSpeechEndMessageEvent = {
3815
+ livespeech_end: "live.speech_end"
3816
+ };
3817
+
3818
+ // src/generated/gladia/schema/callbackLiveSpeechStartMessageEvent.ts
3819
+ var CallbackLiveSpeechStartMessageEvent = {
3820
+ livespeech_start: "live.speech_start"
3821
+ };
3822
+
3823
+ // src/generated/gladia/schema/callbackLiveStartRecordingMessageEvent.ts
3824
+ var CallbackLiveStartRecordingMessageEvent = {
3825
+ livestart_recording: "live.start_recording"
3826
+ };
3827
+
3828
+ // src/generated/gladia/schema/callbackLiveStartSessionMessageEvent.ts
3829
+ var CallbackLiveStartSessionMessageEvent = {
3830
+ livestart_session: "live.start_session"
3831
+ };
3832
+
3833
+ // src/generated/gladia/schema/callbackLiveStopRecordingAckMessageEvent.ts
3834
+ var CallbackLiveStopRecordingAckMessageEvent = {
3835
+ livestop_recording: "live.stop_recording"
3836
+ };
3837
+
3838
+ // src/generated/gladia/schema/callbackLiveTranscriptMessageEvent.ts
3839
+ var CallbackLiveTranscriptMessageEvent = {
3840
+ livetranscript: "live.transcript"
3841
+ };
3842
+
3843
+ // src/generated/gladia/schema/callbackLiveTranslationMessageEvent.ts
3844
+ var CallbackLiveTranslationMessageEvent = {
3845
+ livetranslation: "live.translation"
3846
+ };
3847
+
3848
+ // src/generated/gladia/schema/callbackMethodEnum.ts
3849
+ var CallbackMethodEnum = {
3850
+ POST: "POST",
3851
+ PUT: "PUT"
3852
+ };
3853
+
3854
+ // src/generated/gladia/schema/callbackTranscriptionErrorPayloadEvent.ts
3855
+ var CallbackTranscriptionErrorPayloadEvent = {
3856
+ transcriptionerror: "transcription.error"
3857
+ };
3858
+
3859
+ // src/generated/gladia/schema/callbackTranscriptionSuccessPayloadEvent.ts
3860
+ var CallbackTranscriptionSuccessPayloadEvent = {
3861
+ transcriptionsuccess: "transcription.success"
3862
+ };
3863
+
3864
+ // src/generated/gladia/schema/endRecordingMessageType.ts
3865
+ var EndRecordingMessageType = {
3866
+ end_recording: "end_recording"
3867
+ };
3868
+
3869
+ // src/generated/gladia/schema/endSessionMessageType.ts
3870
+ var EndSessionMessageType = {
3871
+ end_session: "end_session"
3872
+ };
3873
+
3874
+ // src/generated/gladia/schema/historyControllerGetListV1KindItem.ts
3875
+ var HistoryControllerGetListV1KindItem = {
3876
+ "pre-recorded": "pre-recorded",
3877
+ live: "live"
3878
+ };
3879
+
3880
+ // src/generated/gladia/schema/historyControllerGetListV1StatusItem.ts
3881
+ var HistoryControllerGetListV1StatusItem = {
3882
+ queued: "queued",
3883
+ processing: "processing",
3884
+ done: "done",
3885
+ error: "error"
3886
+ };
3887
+
3888
+ // src/generated/gladia/schema/namedEntityRecognitionMessageType.ts
3889
+ var NamedEntityRecognitionMessageType = {
3890
+ named_entity_recognition: "named_entity_recognition"
3891
+ };
3892
+
3893
+ // src/generated/gladia/schema/postChapterizationMessageType.ts
3894
+ var PostChapterizationMessageType = {
3895
+ post_chapterization: "post_chapterization"
3896
+ };
3897
+
3898
+ // src/generated/gladia/schema/postFinalTranscriptMessageType.ts
3899
+ var PostFinalTranscriptMessageType = {
3900
+ post_final_transcript: "post_final_transcript"
3901
+ };
3902
+
3903
+ // src/generated/gladia/schema/postSummarizationMessageType.ts
3904
+ var PostSummarizationMessageType = {
3905
+ post_summarization: "post_summarization"
3906
+ };
3907
+
3908
+ // src/generated/gladia/schema/postTranscriptMessageType.ts
3909
+ var PostTranscriptMessageType = {
3910
+ post_transcript: "post_transcript"
3911
+ };
3912
+
3913
+ // src/generated/gladia/schema/preRecordedControllerGetPreRecordedJobsV2StatusItem.ts
3914
+ var PreRecordedControllerGetPreRecordedJobsV2StatusItem = {
3915
+ queued: "queued",
3916
+ processing: "processing",
3917
+ done: "done",
3918
+ error: "error"
3919
+ };
3920
+
3921
+ // src/generated/gladia/schema/preRecordedResponseKind.ts
3922
+ var PreRecordedResponseKind = {
3923
+ "pre-recorded": "pre-recorded"
3924
+ };
3925
+
3926
+ // src/generated/gladia/schema/preRecordedResponseStatus.ts
3927
+ var PreRecordedResponseStatus = {
3928
+ queued: "queued",
3929
+ processing: "processing",
3930
+ done: "done",
3931
+ error: "error"
3932
+ };
3933
+
3934
+ // src/generated/gladia/schema/sentimentAnalysisMessageType.ts
3935
+ var SentimentAnalysisMessageType = {
3936
+ sentiment_analysis: "sentiment_analysis"
3937
+ };
3938
+
3939
+ // src/generated/gladia/schema/speechEndMessageType.ts
3940
+ var SpeechEndMessageType = {
3941
+ speech_end: "speech_end"
3942
+ };
3943
+
3944
+ // src/generated/gladia/schema/speechStartMessageType.ts
3945
+ var SpeechStartMessageType = {
3946
+ speech_start: "speech_start"
3947
+ };
3948
+
3949
+ // src/generated/gladia/schema/startRecordingMessageType.ts
3950
+ var StartRecordingMessageType = {
3951
+ start_recording: "start_recording"
3952
+ };
3953
+
3954
+ // src/generated/gladia/schema/startSessionMessageType.ts
3955
+ var StartSessionMessageType = {
3956
+ start_session: "start_session"
3957
+ };
3958
+
3959
+ // src/generated/gladia/schema/stopRecordingAckMessageType.ts
3960
+ var StopRecordingAckMessageType = {
3961
+ stop_recording: "stop_recording"
3962
+ };
3963
+
3964
+ // src/generated/gladia/schema/stopRecordingActionType.ts
3965
+ var StopRecordingActionType = {
3966
+ stop_recording: "stop_recording"
3967
+ };
3968
+
3969
+ // src/generated/gladia/schema/streamingControllerGetStreamingJobsV2StatusItem.ts
3970
+ var StreamingControllerGetStreamingJobsV2StatusItem = {
3971
+ queued: "queued",
3972
+ processing: "processing",
3973
+ done: "done",
3974
+ error: "error"
3975
+ };
3976
+
3977
+ // src/generated/gladia/schema/streamingResponseKind.ts
3978
+ var StreamingResponseKind = {
3979
+ live: "live"
3980
+ };
3981
+
3982
+ // src/generated/gladia/schema/streamingResponseStatus.ts
3983
+ var StreamingResponseStatus = {
3984
+ queued: "queued",
3985
+ processing: "processing",
3986
+ done: "done",
3987
+ error: "error"
3988
+ };
3989
+
3990
+ // src/generated/gladia/schema/streamingSupportedBitDepthEnum.ts
3991
+ var StreamingSupportedBitDepthEnum = {
3992
+ NUMBER_8: 8,
3993
+ NUMBER_16: 16,
3994
+ NUMBER_24: 24,
3995
+ NUMBER_32: 32
3996
+ };
3997
+
3998
+ // src/generated/gladia/schema/streamingSupportedEncodingEnum.ts
3999
+ var StreamingSupportedEncodingEnum = {
4000
+ "wav/pcm": "wav/pcm",
4001
+ "wav/alaw": "wav/alaw",
4002
+ "wav/ulaw": "wav/ulaw"
4003
+ };
4004
+
4005
+ // src/generated/gladia/schema/streamingSupportedModels.ts
4006
+ var StreamingSupportedModels = {
4007
+ "solaria-1": "solaria-1"
4008
+ };
4009
+
4010
+ // src/generated/gladia/schema/streamingSupportedRegions.ts
4011
+ var StreamingSupportedRegions = {
4012
+ "us-west": "us-west",
4013
+ "eu-west": "eu-west"
4014
+ };
4015
+
4016
+ // src/generated/gladia/schema/streamingSupportedSampleRateEnum.ts
4017
+ var StreamingSupportedSampleRateEnum = {
4018
+ NUMBER_8000: 8e3,
4019
+ NUMBER_16000: 16e3,
4020
+ NUMBER_32000: 32e3,
4021
+ NUMBER_44100: 44100,
4022
+ NUMBER_48000: 48e3
4023
+ };
4024
+
4025
+ // src/generated/gladia/schema/subtitlesFormatEnum.ts
4026
+ var SubtitlesFormatEnum = {
4027
+ srt: "srt",
4028
+ vtt: "vtt"
4029
+ };
4030
+
4031
+ // src/generated/gladia/schema/subtitlesStyleEnum.ts
4032
+ var SubtitlesStyleEnum = {
4033
+ default: "default",
4034
+ compliance: "compliance"
4035
+ };
4036
+
4037
+ // src/generated/gladia/schema/summaryTypesEnum.ts
4038
+ var SummaryTypesEnum = {
4039
+ general: "general",
4040
+ bullet_points: "bullet_points",
4041
+ concise: "concise"
4042
+ };
4043
+
4044
+ // src/generated/gladia/schema/transcriptMessageType.ts
4045
+ var TranscriptMessageType = {
4046
+ transcript: "transcript"
4047
+ };
4048
+
4049
+ // src/generated/gladia/schema/transcriptionControllerListV2KindItem.ts
4050
+ var TranscriptionControllerListV2KindItem = {
4051
+ "pre-recorded": "pre-recorded",
4052
+ live: "live"
4053
+ };
4054
+
4055
+ // src/generated/gladia/schema/transcriptionControllerListV2StatusItem.ts
4056
+ var TranscriptionControllerListV2StatusItem = {
4057
+ queued: "queued",
4058
+ processing: "processing",
4059
+ done: "done",
4060
+ error: "error"
4061
+ };
4062
+
4063
+ // src/generated/gladia/schema/transcriptionLanguageCodeEnum.ts
4064
+ var TranscriptionLanguageCodeEnum = {
4065
+ af: "af",
4066
+ am: "am",
4067
+ ar: "ar",
4068
+ as: "as",
4069
+ az: "az",
4070
+ ba: "ba",
4071
+ be: "be",
4072
+ bg: "bg",
4073
+ bn: "bn",
4074
+ bo: "bo",
4075
+ br: "br",
4076
+ bs: "bs",
4077
+ ca: "ca",
4078
+ cs: "cs",
4079
+ cy: "cy",
4080
+ da: "da",
4081
+ de: "de",
4082
+ el: "el",
4083
+ en: "en",
4084
+ es: "es",
4085
+ et: "et",
4086
+ eu: "eu",
4087
+ fa: "fa",
4088
+ fi: "fi",
4089
+ fo: "fo",
4090
+ fr: "fr",
4091
+ gl: "gl",
4092
+ gu: "gu",
4093
+ ha: "ha",
4094
+ haw: "haw",
4095
+ he: "he",
4096
+ hi: "hi",
4097
+ hr: "hr",
4098
+ ht: "ht",
4099
+ hu: "hu",
4100
+ hy: "hy",
4101
+ id: "id",
4102
+ is: "is",
4103
+ it: "it",
4104
+ ja: "ja",
4105
+ jw: "jw",
4106
+ ka: "ka",
4107
+ kk: "kk",
4108
+ km: "km",
4109
+ kn: "kn",
4110
+ ko: "ko",
4111
+ la: "la",
4112
+ lb: "lb",
4113
+ ln: "ln",
4114
+ lo: "lo",
4115
+ lt: "lt",
4116
+ lv: "lv",
4117
+ mg: "mg",
4118
+ mi: "mi",
4119
+ mk: "mk",
4120
+ ml: "ml",
4121
+ mn: "mn",
4122
+ mr: "mr",
4123
+ ms: "ms",
4124
+ mt: "mt",
4125
+ my: "my",
4126
+ ne: "ne",
4127
+ nl: "nl",
4128
+ nn: "nn",
4129
+ no: "no",
4130
+ oc: "oc",
4131
+ pa: "pa",
4132
+ pl: "pl",
4133
+ ps: "ps",
4134
+ pt: "pt",
4135
+ ro: "ro",
4136
+ ru: "ru",
4137
+ sa: "sa",
4138
+ sd: "sd",
4139
+ si: "si",
4140
+ sk: "sk",
4141
+ sl: "sl",
4142
+ sn: "sn",
4143
+ so: "so",
4144
+ sq: "sq",
4145
+ sr: "sr",
4146
+ su: "su",
4147
+ sv: "sv",
4148
+ sw: "sw",
4149
+ ta: "ta",
4150
+ te: "te",
4151
+ tg: "tg",
4152
+ th: "th",
4153
+ tk: "tk",
4154
+ tl: "tl",
4155
+ tr: "tr",
4156
+ tt: "tt",
4157
+ uk: "uk",
4158
+ ur: "ur",
4159
+ uz: "uz",
4160
+ vi: "vi",
4161
+ yi: "yi",
4162
+ yo: "yo",
4163
+ zh: "zh"
4164
+ };
4165
+
4166
+ // src/generated/gladia/schema/translationLanguageCodeEnum.ts
4167
+ var TranslationLanguageCodeEnum = {
4168
+ af: "af",
4169
+ am: "am",
4170
+ ar: "ar",
4171
+ as: "as",
4172
+ az: "az",
4173
+ ba: "ba",
4174
+ be: "be",
4175
+ bg: "bg",
4176
+ bn: "bn",
4177
+ bo: "bo",
4178
+ br: "br",
4179
+ bs: "bs",
4180
+ ca: "ca",
4181
+ cs: "cs",
4182
+ cy: "cy",
4183
+ da: "da",
4184
+ de: "de",
4185
+ el: "el",
4186
+ en: "en",
4187
+ es: "es",
4188
+ et: "et",
4189
+ eu: "eu",
4190
+ fa: "fa",
4191
+ fi: "fi",
4192
+ fo: "fo",
4193
+ fr: "fr",
4194
+ gl: "gl",
4195
+ gu: "gu",
4196
+ ha: "ha",
4197
+ haw: "haw",
4198
+ he: "he",
4199
+ hi: "hi",
4200
+ hr: "hr",
4201
+ ht: "ht",
4202
+ hu: "hu",
4203
+ hy: "hy",
4204
+ id: "id",
4205
+ is: "is",
4206
+ it: "it",
4207
+ ja: "ja",
4208
+ jw: "jw",
4209
+ ka: "ka",
4210
+ kk: "kk",
4211
+ km: "km",
4212
+ kn: "kn",
4213
+ ko: "ko",
4214
+ la: "la",
4215
+ lb: "lb",
4216
+ ln: "ln",
4217
+ lo: "lo",
4218
+ lt: "lt",
4219
+ lv: "lv",
4220
+ mg: "mg",
4221
+ mi: "mi",
4222
+ mk: "mk",
4223
+ ml: "ml",
4224
+ mn: "mn",
4225
+ mr: "mr",
4226
+ ms: "ms",
4227
+ mt: "mt",
4228
+ my: "my",
4229
+ ne: "ne",
4230
+ nl: "nl",
4231
+ nn: "nn",
4232
+ no: "no",
4233
+ oc: "oc",
4234
+ pa: "pa",
4235
+ pl: "pl",
4236
+ ps: "ps",
4237
+ pt: "pt",
4238
+ ro: "ro",
4239
+ ru: "ru",
4240
+ sa: "sa",
4241
+ sd: "sd",
4242
+ si: "si",
4243
+ sk: "sk",
4244
+ sl: "sl",
4245
+ sn: "sn",
4246
+ so: "so",
4247
+ sq: "sq",
4248
+ sr: "sr",
4249
+ su: "su",
4250
+ sv: "sv",
4251
+ sw: "sw",
4252
+ ta: "ta",
4253
+ te: "te",
4254
+ tg: "tg",
4255
+ th: "th",
4256
+ tk: "tk",
4257
+ tl: "tl",
4258
+ tr: "tr",
4259
+ tt: "tt",
4260
+ uk: "uk",
4261
+ ur: "ur",
4262
+ uz: "uz",
4263
+ vi: "vi",
4264
+ wo: "wo",
4265
+ yi: "yi",
4266
+ yo: "yo",
4267
+ zh: "zh"
4268
+ };
4269
+
4270
+ // src/generated/gladia/schema/translationMessageType.ts
4271
+ var TranslationMessageType = {
4272
+ translation: "translation"
4273
+ };
4274
+
4275
+ // src/generated/gladia/schema/translationModelEnum.ts
4276
+ var TranslationModelEnum = {
4277
+ base: "base",
4278
+ enhanced: "enhanced"
4279
+ };
4280
+
4281
+ // src/generated/gladia/schema/videoToTextControllerVideoTranscriptionBodyLanguage.ts
4282
+ var VideoToTextControllerVideoTranscriptionBodyLanguage = {
4283
+ afrikaans: "afrikaans",
4284
+ albanian: "albanian",
4285
+ amharic: "amharic",
4286
+ arabic: "arabic",
4287
+ armenian: "armenian",
4288
+ assamese: "assamese",
4289
+ azerbaijani: "azerbaijani",
4290
+ bashkir: "bashkir",
4291
+ basque: "basque",
4292
+ belarusian: "belarusian",
4293
+ bengali: "bengali",
4294
+ bosnian: "bosnian",
4295
+ breton: "breton",
4296
+ bulgarian: "bulgarian",
4297
+ catalan: "catalan",
4298
+ chinese: "chinese",
4299
+ croatian: "croatian",
4300
+ czech: "czech",
4301
+ danish: "danish",
4302
+ dutch: "dutch",
4303
+ english: "english",
4304
+ estonian: "estonian",
4305
+ faroese: "faroese",
4306
+ finnish: "finnish",
4307
+ french: "french",
4308
+ galician: "galician",
4309
+ georgian: "georgian",
4310
+ german: "german",
4311
+ greek: "greek",
4312
+ gujarati: "gujarati",
4313
+ haitian_creole: "haitian creole",
4314
+ hausa: "hausa",
4315
+ hawaiian: "hawaiian",
4316
+ hebrew: "hebrew",
4317
+ hindi: "hindi",
4318
+ hungarian: "hungarian",
4319
+ icelandic: "icelandic",
4320
+ indonesian: "indonesian",
4321
+ italian: "italian",
4322
+ japanese: "japanese",
4323
+ javanese: "javanese",
4324
+ kannada: "kannada",
4325
+ kazakh: "kazakh",
4326
+ khmer: "khmer",
4327
+ korean: "korean",
4328
+ lao: "lao",
4329
+ latin: "latin",
4330
+ latvian: "latvian",
4331
+ lingala: "lingala",
4332
+ lithuanian: "lithuanian",
4333
+ luxembourgish: "luxembourgish",
4334
+ macedonian: "macedonian",
4335
+ malagasy: "malagasy",
4336
+ malay: "malay",
4337
+ malayalam: "malayalam",
4338
+ maltese: "maltese",
4339
+ maori: "maori",
4340
+ marathi: "marathi",
4341
+ mongolian: "mongolian",
4342
+ myanmar: "myanmar",
4343
+ nepali: "nepali",
4344
+ norwegian: "norwegian",
4345
+ nynorsk: "nynorsk",
4346
+ occitan: "occitan",
4347
+ pashto: "pashto",
4348
+ persian: "persian",
4349
+ polish: "polish",
4350
+ portuguese: "portuguese",
4351
+ punjabi: "punjabi",
4352
+ romanian: "romanian",
4353
+ russian: "russian",
4354
+ sanskrit: "sanskrit",
4355
+ serbian: "serbian",
4356
+ shona: "shona",
4357
+ sindhi: "sindhi",
4358
+ sinhala: "sinhala",
4359
+ slovak: "slovak",
4360
+ slovenian: "slovenian",
4361
+ somali: "somali",
4362
+ spanish: "spanish",
4363
+ sundanese: "sundanese",
4364
+ swahili: "swahili",
4365
+ swedish: "swedish",
4366
+ tagalog: "tagalog",
4367
+ tajik: "tajik",
4368
+ tamil: "tamil",
4369
+ tatar: "tatar",
4370
+ telugu: "telugu",
4371
+ thai: "thai",
4372
+ tibetan: "tibetan",
4373
+ turkish: "turkish",
4374
+ turkmen: "turkmen",
4375
+ ukrainian: "ukrainian",
4376
+ urdu: "urdu",
4377
+ uzbek: "uzbek",
4378
+ vietnamese: "vietnamese",
4379
+ welsh: "welsh",
4380
+ yiddish: "yiddish",
4381
+ yoruba: "yoruba"
4382
+ };
4383
+
4384
+ // src/generated/gladia/schema/videoToTextControllerVideoTranscriptionBodyLanguageBehaviour.ts
4385
+ var VideoToTextControllerVideoTranscriptionBodyLanguageBehaviour = {
4386
+ automatic_single_language: "automatic single language",
4387
+ automatic_multiple_languages: "automatic multiple languages",
4388
+ manual: "manual"
4389
+ };
4390
+
4391
+ // src/generated/gladia/schema/videoToTextControllerVideoTranscriptionBodyOutputFormat.ts
4392
+ var VideoToTextControllerVideoTranscriptionBodyOutputFormat = {
4393
+ json: "json",
4394
+ srt: "srt",
4395
+ vtt: "vtt",
4396
+ plain: "plain",
4397
+ txt: "txt"
4398
+ };
4399
+
4400
+ // src/generated/gladia/schema/videoToTextControllerVideoTranscriptionBodyTargetTranslationLanguage.ts
4401
+ var VideoToTextControllerVideoTranscriptionBodyTargetTranslationLanguage = {
4402
+ afrikaans: "afrikaans",
4403
+ albanian: "albanian",
4404
+ amharic: "amharic",
4405
+ arabic: "arabic",
4406
+ armenian: "armenian",
4407
+ assamese: "assamese",
4408
+ azerbaijani: "azerbaijani",
4409
+ bashkir: "bashkir",
4410
+ basque: "basque",
4411
+ belarusian: "belarusian",
4412
+ bengali: "bengali",
4413
+ bosnian: "bosnian",
4414
+ breton: "breton",
4415
+ bulgarian: "bulgarian",
4416
+ catalan: "catalan",
4417
+ chinese: "chinese",
4418
+ croatian: "croatian",
4419
+ czech: "czech",
4420
+ danish: "danish",
4421
+ dutch: "dutch",
4422
+ english: "english",
4423
+ estonian: "estonian",
4424
+ faroese: "faroese",
4425
+ finnish: "finnish",
4426
+ french: "french",
4427
+ galician: "galician",
4428
+ georgian: "georgian",
4429
+ german: "german",
4430
+ greek: "greek",
4431
+ gujarati: "gujarati",
4432
+ haitian_creole: "haitian creole",
4433
+ hausa: "hausa",
4434
+ hawaiian: "hawaiian",
4435
+ hebrew: "hebrew",
4436
+ hindi: "hindi",
4437
+ hungarian: "hungarian",
4438
+ icelandic: "icelandic",
4439
+ indonesian: "indonesian",
4440
+ italian: "italian",
4441
+ japanese: "japanese",
4442
+ javanese: "javanese",
4443
+ kannada: "kannada",
4444
+ kazakh: "kazakh",
4445
+ khmer: "khmer",
4446
+ korean: "korean",
4447
+ lao: "lao",
4448
+ latin: "latin",
4449
+ latvian: "latvian",
4450
+ lingala: "lingala",
4451
+ lithuanian: "lithuanian",
4452
+ luxembourgish: "luxembourgish",
4453
+ macedonian: "macedonian",
4454
+ malagasy: "malagasy",
4455
+ malay: "malay",
4456
+ malayalam: "malayalam",
4457
+ maltese: "maltese",
4458
+ maori: "maori",
4459
+ marathi: "marathi",
4460
+ mongolian: "mongolian",
4461
+ myanmar: "myanmar",
4462
+ nepali: "nepali",
4463
+ norwegian: "norwegian",
4464
+ nynorsk: "nynorsk",
4465
+ occitan: "occitan",
4466
+ pashto: "pashto",
4467
+ persian: "persian",
4468
+ polish: "polish",
4469
+ portuguese: "portuguese",
4470
+ punjabi: "punjabi",
4471
+ romanian: "romanian",
4472
+ russian: "russian",
4473
+ sanskrit: "sanskrit",
4474
+ serbian: "serbian",
4475
+ shona: "shona",
4476
+ sindhi: "sindhi",
4477
+ sinhala: "sinhala",
4478
+ slovak: "slovak",
4479
+ slovenian: "slovenian",
4480
+ somali: "somali",
4481
+ spanish: "spanish",
4482
+ sundanese: "sundanese",
4483
+ swahili: "swahili",
4484
+ swedish: "swedish",
4485
+ tagalog: "tagalog",
4486
+ tajik: "tajik",
4487
+ tamil: "tamil",
4488
+ tatar: "tatar",
4489
+ telugu: "telugu",
4490
+ thai: "thai",
4491
+ tibetan: "tibetan",
4492
+ turkish: "turkish",
4493
+ turkmen: "turkmen",
4494
+ ukrainian: "ukrainian",
4495
+ urdu: "urdu",
4496
+ uzbek: "uzbek",
4497
+ vietnamese: "vietnamese",
4498
+ welsh: "welsh",
4499
+ wolof: "wolof",
4500
+ yiddish: "yiddish",
4501
+ yoruba: "yoruba"
4502
+ };
4503
+
4504
+ // src/generated/gladia/schema/webhookLiveEndRecordingPayloadEvent.ts
4505
+ var WebhookLiveEndRecordingPayloadEvent = {
4506
+ liveend_recording: "live.end_recording"
4507
+ };
4508
+
4509
+ // src/generated/gladia/schema/webhookLiveEndSessionPayloadEvent.ts
4510
+ var WebhookLiveEndSessionPayloadEvent = {
4511
+ liveend_session: "live.end_session"
4512
+ };
4513
+
4514
+ // src/generated/gladia/schema/webhookLiveStartRecordingPayloadEvent.ts
4515
+ var WebhookLiveStartRecordingPayloadEvent = {
4516
+ livestart_recording: "live.start_recording"
4517
+ };
4518
+
4519
+ // src/generated/gladia/schema/webhookLiveStartSessionPayloadEvent.ts
4520
+ var WebhookLiveStartSessionPayloadEvent = {
4521
+ livestart_session: "live.start_session"
4522
+ };
4523
+
4524
+ // src/generated/gladia/schema/webhookTranscriptionCreatedPayloadEvent.ts
4525
+ var WebhookTranscriptionCreatedPayloadEvent = {
4526
+ transcriptioncreated: "transcription.created"
4527
+ };
4528
+
4529
+ // src/generated/gladia/schema/webhookTranscriptionErrorPayloadEvent.ts
4530
+ var WebhookTranscriptionErrorPayloadEvent = {
4531
+ transcriptionerror: "transcription.error"
4532
+ };
4533
+
4534
+ // src/generated/gladia/schema/webhookTranscriptionSuccessPayloadEvent.ts
4535
+ var WebhookTranscriptionSuccessPayloadEvent = {
4536
+ transcriptionsuccess: "transcription.success"
4537
+ };
4538
+
4539
+ // src/generated/assemblyai/schema/index.ts
4540
+ var schema_exports2 = {};
4541
+ __export(schema_exports2, {
4542
+ AudioIntelligenceModelStatus: () => AudioIntelligenceModelStatus,
4543
+ EntityType: () => EntityType,
4544
+ LemurModel: () => LemurModel,
4545
+ PiiPolicy: () => PiiPolicy,
4546
+ RedactPiiAudioQuality: () => RedactPiiAudioQuality,
4547
+ RedactedAudioStatus: () => RedactedAudioStatus,
4548
+ Sentiment: () => Sentiment,
4549
+ SpeechModel: () => SpeechModel,
4550
+ SubstitutionPolicy: () => SubstitutionPolicy,
4551
+ SubtitleFormat: () => SubtitleFormat,
4552
+ SummaryModel: () => SummaryModel,
4553
+ SummaryType: () => SummaryType,
4554
+ TranscriptBoostParam: () => TranscriptBoostParam,
4555
+ TranscriptLanguageCode: () => TranscriptLanguageCode,
4556
+ TranscriptReadyStatus: () => TranscriptReadyStatus,
4557
+ TranscriptStatus: () => TranscriptStatus
4558
+ });
4559
+
4560
+ // src/generated/assemblyai/schema/audioIntelligenceModelStatus.ts
4561
+ var AudioIntelligenceModelStatus = {
4562
+ success: "success",
4563
+ unavailable: "unavailable"
4564
+ };
4565
+
4566
+ // src/generated/assemblyai/schema/entityType.ts
4567
+ var EntityType = {
4568
+ account_number: "account_number",
4569
+ banking_information: "banking_information",
4570
+ blood_type: "blood_type",
4571
+ credit_card_cvv: "credit_card_cvv",
4572
+ credit_card_expiration: "credit_card_expiration",
4573
+ credit_card_number: "credit_card_number",
4574
+ date: "date",
4575
+ date_interval: "date_interval",
4576
+ date_of_birth: "date_of_birth",
4577
+ drivers_license: "drivers_license",
4578
+ drug: "drug",
4579
+ duration: "duration",
4580
+ email_address: "email_address",
4581
+ event: "event",
4582
+ filename: "filename",
4583
+ gender_sexuality: "gender_sexuality",
4584
+ healthcare_number: "healthcare_number",
4585
+ injury: "injury",
4586
+ ip_address: "ip_address",
4587
+ language: "language",
4588
+ location: "location",
4589
+ marital_status: "marital_status",
4590
+ medical_condition: "medical_condition",
4591
+ medical_process: "medical_process",
4592
+ money_amount: "money_amount",
4593
+ nationality: "nationality",
4594
+ number_sequence: "number_sequence",
4595
+ occupation: "occupation",
4596
+ organization: "organization",
4597
+ passport_number: "passport_number",
4598
+ password: "password",
4599
+ person_age: "person_age",
4600
+ person_name: "person_name",
4601
+ phone_number: "phone_number",
4602
+ physical_attribute: "physical_attribute",
4603
+ political_affiliation: "political_affiliation",
4604
+ religion: "religion",
4605
+ statistics: "statistics",
4606
+ time: "time",
4607
+ url: "url",
4608
+ us_social_security_number: "us_social_security_number",
4609
+ username: "username",
4610
+ vehicle_id: "vehicle_id",
4611
+ zodiac_sign: "zodiac_sign"
4612
+ };
4613
+
4614
+ // src/generated/assemblyai/schema/lemurModel.ts
4615
+ var LemurModel = {
4616
+ "anthropic/claude-3-5-sonnet": "anthropic/claude-3-5-sonnet",
4617
+ "anthropic/claude-3-opus": "anthropic/claude-3-opus",
4618
+ "anthropic/claude-3-haiku": "anthropic/claude-3-haiku"
4619
+ };
4620
+
4621
+ // src/generated/assemblyai/schema/piiPolicy.ts
4622
+ var PiiPolicy = {
4623
+ account_number: "account_number",
4624
+ banking_information: "banking_information",
4625
+ blood_type: "blood_type",
4626
+ credit_card_cvv: "credit_card_cvv",
4627
+ credit_card_expiration: "credit_card_expiration",
4628
+ credit_card_number: "credit_card_number",
4629
+ date: "date",
4630
+ date_interval: "date_interval",
4631
+ date_of_birth: "date_of_birth",
4632
+ drivers_license: "drivers_license",
4633
+ drug: "drug",
4634
+ duration: "duration",
4635
+ email_address: "email_address",
4636
+ event: "event",
4637
+ filename: "filename",
4638
+ gender_sexuality: "gender_sexuality",
4639
+ healthcare_number: "healthcare_number",
4640
+ injury: "injury",
4641
+ ip_address: "ip_address",
4642
+ language: "language",
4643
+ location: "location",
4644
+ marital_status: "marital_status",
4645
+ medical_condition: "medical_condition",
4646
+ medical_process: "medical_process",
4647
+ money_amount: "money_amount",
4648
+ nationality: "nationality",
4649
+ number_sequence: "number_sequence",
4650
+ occupation: "occupation",
4651
+ organization: "organization",
4652
+ passport_number: "passport_number",
4653
+ password: "password",
4654
+ person_age: "person_age",
4655
+ person_name: "person_name",
4656
+ phone_number: "phone_number",
4657
+ physical_attribute: "physical_attribute",
4658
+ political_affiliation: "political_affiliation",
4659
+ religion: "religion",
4660
+ statistics: "statistics",
4661
+ time: "time",
4662
+ url: "url",
4663
+ us_social_security_number: "us_social_security_number",
4664
+ username: "username",
4665
+ vehicle_id: "vehicle_id",
4666
+ zodiac_sign: "zodiac_sign"
4667
+ };
4668
+
4669
+ // src/generated/assemblyai/schema/redactPiiAudioQuality.ts
4670
+ var RedactPiiAudioQuality = {
4671
+ mp3: "mp3",
4672
+ wav: "wav"
4673
+ };
4674
+
4675
+ // src/generated/assemblyai/schema/redactedAudioStatus.ts
4676
+ var RedactedAudioStatus = {
4677
+ redacted_audio_ready: "redacted_audio_ready"
4678
+ };
4679
+
4680
+ // src/generated/assemblyai/schema/sentiment.ts
4681
+ var Sentiment = {
4682
+ POSITIVE: "POSITIVE",
4683
+ NEUTRAL: "NEUTRAL",
4684
+ NEGATIVE: "NEGATIVE"
4685
+ };
4686
+
4687
+ // src/generated/assemblyai/schema/speechModel.ts
4688
+ var SpeechModel = {
4689
+ best: "best",
4690
+ "slam-1": "slam-1",
4691
+ universal: "universal"
4692
+ };
4693
+
4694
+ // src/generated/assemblyai/schema/substitutionPolicy.ts
4695
+ var SubstitutionPolicy = {
4696
+ entity_name: "entity_name",
4697
+ hash: "hash"
4698
+ };
4699
+
4700
+ // src/generated/assemblyai/schema/subtitleFormat.ts
4701
+ var SubtitleFormat = {
4702
+ srt: "srt",
4703
+ vtt: "vtt"
4704
+ };
4705
+
4706
+ // src/generated/assemblyai/schema/summaryModel.ts
4707
+ var SummaryModel = {
4708
+ informative: "informative",
4709
+ conversational: "conversational",
4710
+ catchy: "catchy"
4711
+ };
4712
+
4713
+ // src/generated/assemblyai/schema/summaryType.ts
4714
+ var SummaryType = {
4715
+ bullets: "bullets",
4716
+ bullets_verbose: "bullets_verbose",
4717
+ gist: "gist",
4718
+ headline: "headline",
4719
+ paragraph: "paragraph"
4720
+ };
4721
+
4722
+ // src/generated/assemblyai/schema/transcriptBoostParam.ts
4723
+ var TranscriptBoostParam = {
4724
+ low: "low",
4725
+ default: "default",
4726
+ high: "high"
4727
+ };
4728
+
4729
+ // src/generated/assemblyai/schema/transcriptLanguageCode.ts
4730
+ var TranscriptLanguageCode = {
4731
+ en: "en",
4732
+ en_au: "en_au",
4733
+ en_uk: "en_uk",
4734
+ en_us: "en_us",
4735
+ es: "es",
4736
+ fr: "fr",
4737
+ de: "de",
4738
+ it: "it",
4739
+ pt: "pt",
4740
+ nl: "nl",
4741
+ af: "af",
4742
+ sq: "sq",
4743
+ am: "am",
4744
+ ar: "ar",
4745
+ hy: "hy",
4746
+ as: "as",
4747
+ az: "az",
4748
+ ba: "ba",
4749
+ eu: "eu",
4750
+ be: "be",
4751
+ bn: "bn",
4752
+ bs: "bs",
4753
+ br: "br",
4754
+ bg: "bg",
4755
+ my: "my",
4756
+ ca: "ca",
4757
+ zh: "zh",
4758
+ hr: "hr",
4759
+ cs: "cs",
4760
+ da: "da",
4761
+ et: "et",
4762
+ fo: "fo",
4763
+ fi: "fi",
4764
+ gl: "gl",
4765
+ ka: "ka",
4766
+ el: "el",
4767
+ gu: "gu",
4768
+ ht: "ht",
4769
+ ha: "ha",
4770
+ haw: "haw",
4771
+ he: "he",
4772
+ hi: "hi",
4773
+ hu: "hu",
4774
+ is: "is",
4775
+ id: "id",
4776
+ ja: "ja",
4777
+ jw: "jw",
4778
+ kn: "kn",
4779
+ kk: "kk",
4780
+ km: "km",
4781
+ ko: "ko",
4782
+ lo: "lo",
4783
+ la: "la",
4784
+ lv: "lv",
4785
+ ln: "ln",
4786
+ lt: "lt",
4787
+ lb: "lb",
4788
+ mk: "mk",
4789
+ mg: "mg",
4790
+ ms: "ms",
4791
+ ml: "ml",
4792
+ mt: "mt",
4793
+ mi: "mi",
4794
+ mr: "mr",
4795
+ mn: "mn",
4796
+ ne: "ne",
4797
+ no: "no",
4798
+ nn: "nn",
4799
+ oc: "oc",
4800
+ pa: "pa",
4801
+ ps: "ps",
4802
+ fa: "fa",
4803
+ pl: "pl",
4804
+ ro: "ro",
4805
+ ru: "ru",
4806
+ sa: "sa",
4807
+ sr: "sr",
4808
+ sn: "sn",
4809
+ sd: "sd",
4810
+ si: "si",
4811
+ sk: "sk",
4812
+ sl: "sl",
4813
+ so: "so",
4814
+ su: "su",
4815
+ sw: "sw",
4816
+ sv: "sv",
4817
+ tl: "tl",
4818
+ tg: "tg",
4819
+ ta: "ta",
4820
+ tt: "tt",
4821
+ te: "te",
4822
+ th: "th",
4823
+ bo: "bo",
4824
+ tr: "tr",
4825
+ tk: "tk",
4826
+ uk: "uk",
4827
+ ur: "ur",
4828
+ uz: "uz",
4829
+ vi: "vi",
4830
+ cy: "cy",
4831
+ yi: "yi",
4832
+ yo: "yo"
4833
+ };
4834
+
4835
+ // src/generated/assemblyai/schema/transcriptReadyStatus.ts
4836
+ var TranscriptReadyStatus = {
4837
+ completed: "completed",
4838
+ error: "error"
4839
+ };
4840
+
4841
+ // src/generated/assemblyai/schema/transcriptStatus.ts
4842
+ var TranscriptStatus = {
4843
+ queued: "queued",
4844
+ processing: "processing",
4845
+ completed: "completed",
4846
+ error: "error"
4847
+ };
4848
+ // Annotate the CommonJS export names for ESM import in node:
4849
+ 0 && (module.exports = {
4850
+ AssemblyAIAdapter,
4851
+ AssemblyAITypes,
4852
+ AssemblyAIWebhookHandler,
4853
+ AzureSTTAdapter,
4854
+ AzureWebhookHandler,
4855
+ BaseAdapter,
4856
+ BaseWebhookHandler,
4857
+ DeepgramAdapter,
4858
+ DeepgramWebhookHandler,
4859
+ GladiaAdapter,
4860
+ GladiaTypes,
4861
+ GladiaWebhookHandler,
4862
+ OpenAIWhisperAdapter,
4863
+ SpeechmaticsAdapter,
4864
+ SpeechmaticsWebhookHandler,
4865
+ VoiceRouter,
4866
+ WebhookRouter,
4867
+ createAssemblyAIAdapter,
4868
+ createAssemblyAIWebhookHandler,
4869
+ createAzureSTTAdapter,
4870
+ createAzureWebhookHandler,
4871
+ createDeepgramAdapter,
4872
+ createDeepgramWebhookHandler,
4873
+ createGladiaAdapter,
4874
+ createGladiaWebhookHandler,
4875
+ createOpenAIWhisperAdapter,
4876
+ createSpeechmaticsAdapter,
4877
+ createVoiceRouter,
4878
+ createWebhookRouter
4879
+ });
4880
+ //# sourceMappingURL=index.js.map