@ai-sdk/deepgram 2.0.7 → 2.0.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @ai-sdk/deepgram
2
2
 
3
+ ## 2.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - 8dc54db: chore: add src folders to package bundle
8
+
9
+ ## 2.0.8
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [5c090e7]
14
+ - @ai-sdk/provider@3.0.4
15
+ - @ai-sdk/provider-utils@4.0.8
16
+
3
17
  ## 2.0.7
4
18
 
5
19
  ### Patch Changes
package/dist/index.js CHANGED
@@ -593,7 +593,7 @@ var DeepgramSpeechModel = class {
593
593
  };
594
594
 
595
595
  // src/version.ts
596
- var VERSION = true ? "2.0.7" : "0.0.0-test";
596
+ var VERSION = true ? "2.0.9" : "0.0.0-test";
597
597
 
598
598
  // src/deepgram-provider.ts
599
599
  function createDeepgram(options = {}) {
package/dist/index.mjs CHANGED
@@ -579,7 +579,7 @@ var DeepgramSpeechModel = class {
579
579
  };
580
580
 
581
581
  // src/version.ts
582
- var VERSION = true ? "2.0.7" : "0.0.0-test";
582
+ var VERSION = true ? "2.0.9" : "0.0.0-test";
583
583
 
584
584
  // src/deepgram-provider.ts
585
585
  function createDeepgram(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/deepgram",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -8,6 +8,7 @@
8
8
  "types": "./dist/index.d.ts",
9
9
  "files": [
10
10
  "dist/**/*",
11
+ "src",
11
12
  "CHANGELOG.md",
12
13
  "README.md"
13
14
  ],
@@ -20,15 +21,15 @@
20
21
  }
21
22
  },
22
23
  "dependencies": {
23
- "@ai-sdk/provider": "3.0.3",
24
- "@ai-sdk/provider-utils": "4.0.7"
24
+ "@ai-sdk/provider": "3.0.4",
25
+ "@ai-sdk/provider-utils": "4.0.8"
25
26
  },
26
27
  "devDependencies": {
27
28
  "@types/node": "20.17.24",
28
29
  "tsup": "^8",
29
30
  "typescript": "5.6.3",
30
31
  "zod": "3.25.76",
31
- "@ai-sdk/test-server": "1.0.1",
32
+ "@ai-sdk/test-server": "1.0.2",
32
33
  "@vercel/ai-tsconfig": "0.0.0"
33
34
  },
34
35
  "peerDependencies": {
@@ -0,0 +1,36 @@
1
+ export type DeepgramTranscriptionAPITypes = {
2
+ // Base parameters
3
+ language?: string;
4
+ detect_language?: boolean;
5
+ model?: string;
6
+
7
+ // Formatting options
8
+ smart_format?: boolean;
9
+ punctuate?: boolean;
10
+ paragraphs?: boolean;
11
+
12
+ // Summarization and analysis
13
+ summarize?: 'v2' | false;
14
+ topics?: boolean;
15
+ intents?: boolean;
16
+ sentiment?: boolean;
17
+
18
+ // Entity detection
19
+ detect_entities?: boolean;
20
+
21
+ // Redaction options
22
+ redact?: string | string[];
23
+ replace?: string;
24
+
25
+ // Search and keywords
26
+ search?: string;
27
+ keyterm?: string;
28
+
29
+ // Speaker-related features
30
+ diarize?: boolean;
31
+ utterances?: boolean;
32
+ utt_split?: number;
33
+
34
+ // Miscellaneous
35
+ filler_words?: boolean;
36
+ };
@@ -0,0 +1,9 @@
1
+ import { FetchFunction } from '@ai-sdk/provider-utils';
2
+
3
+ export type DeepgramConfig = {
4
+ provider: string;
5
+ url: (options: { modelId: string; path: string }) => string;
6
+ headers: () => Record<string, string | undefined>;
7
+ fetch?: FetchFunction;
8
+ generateId?: () => string;
9
+ };
@@ -0,0 +1,34 @@
1
+ import { safeParseJSON } from '@ai-sdk/provider-utils';
2
+ import { deepgramErrorDataSchema } from './deepgram-error';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ describe('deepgramErrorDataSchema', () => {
6
+ it('should parse Deepgram resource exhausted error', async () => {
7
+ const error = `
8
+ {"error":{"message":"{\\n \\"error\\": {\\n \\"code\\": 429,\\n \\"message\\": \\"Resource has been exhausted (e.g. check quota).\\",\\n \\"status\\": \\"RESOURCE_EXHAUSTED\\"\\n }\\n}\\n","code":429}}
9
+ `;
10
+
11
+ const result = await safeParseJSON({
12
+ text: error,
13
+ schema: deepgramErrorDataSchema,
14
+ });
15
+
16
+ expect(result).toStrictEqual({
17
+ success: true,
18
+ value: {
19
+ error: {
20
+ message:
21
+ '{\n "error": {\n "code": 429,\n "message": "Resource has been exhausted (e.g. check quota).",\n "status": "RESOURCE_EXHAUSTED"\n }\n}\n',
22
+ code: 429,
23
+ },
24
+ },
25
+ rawValue: {
26
+ error: {
27
+ message:
28
+ '{\n "error": {\n "code": 429,\n "message": "Resource has been exhausted (e.g. check quota).",\n "status": "RESOURCE_EXHAUSTED"\n }\n}\n',
29
+ code: 429,
30
+ },
31
+ },
32
+ });
33
+ });
34
+ });
@@ -0,0 +1,16 @@
1
+ import { z } from 'zod/v4';
2
+ import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';
3
+
4
+ export const deepgramErrorDataSchema = z.object({
5
+ error: z.object({
6
+ message: z.string(),
7
+ code: z.number(),
8
+ }),
9
+ });
10
+
11
+ export type DeepgramErrorData = z.infer<typeof deepgramErrorDataSchema>;
12
+
13
+ export const deepgramFailedResponseHandler = createJsonErrorResponseHandler({
14
+ errorSchema: deepgramErrorDataSchema,
15
+ errorToMessage: data => data.error.message,
16
+ });
@@ -0,0 +1,139 @@
1
+ import {
2
+ TranscriptionModelV3,
3
+ SpeechModelV3,
4
+ ProviderV3,
5
+ NoSuchModelError,
6
+ } from '@ai-sdk/provider';
7
+ import {
8
+ FetchFunction,
9
+ loadApiKey,
10
+ withUserAgentSuffix,
11
+ } from '@ai-sdk/provider-utils';
12
+ import { DeepgramTranscriptionModel } from './deepgram-transcription-model';
13
+ import { DeepgramTranscriptionModelId } from './deepgram-transcription-options';
14
+ import { DeepgramSpeechModel } from './deepgram-speech-model';
15
+ import { DeepgramSpeechModelId } from './deepgram-speech-options';
16
+ import { VERSION } from './version';
17
+
18
+ export interface DeepgramProvider extends ProviderV3 {
19
+ (
20
+ modelId: 'nova-3',
21
+ settings?: {},
22
+ ): {
23
+ transcription: DeepgramTranscriptionModel;
24
+ };
25
+
26
+ /**
27
+ Creates a model for transcription.
28
+ */
29
+ transcription(modelId: DeepgramTranscriptionModelId): TranscriptionModelV3;
30
+
31
+ /**
32
+ Creates a model for speech generation.
33
+ */
34
+ speech(modelId: DeepgramSpeechModelId): SpeechModelV3;
35
+
36
+ /**
37
+ * @deprecated Use `embeddingModel` instead.
38
+ */
39
+ textEmbeddingModel(modelId: string): never;
40
+ }
41
+
42
+ export interface DeepgramProviderSettings {
43
+ /**
44
+ API key for authenticating requests.
45
+ */
46
+ apiKey?: string;
47
+
48
+ /**
49
+ Custom headers to include in the requests.
50
+ */
51
+ headers?: Record<string, string>;
52
+
53
+ /**
54
+ Custom fetch implementation. You can use it as a middleware to intercept requests,
55
+ or to provide a custom fetch implementation for e.g. testing.
56
+ */
57
+ fetch?: FetchFunction;
58
+ }
59
+
60
+ /**
61
+ Create an Deepgram provider instance.
62
+ */
63
+ export function createDeepgram(
64
+ options: DeepgramProviderSettings = {},
65
+ ): DeepgramProvider {
66
+ const getHeaders = () =>
67
+ withUserAgentSuffix(
68
+ {
69
+ authorization: `Token ${loadApiKey({
70
+ apiKey: options.apiKey,
71
+ environmentVariableName: 'DEEPGRAM_API_KEY',
72
+ description: 'Deepgram',
73
+ })}`,
74
+ ...options.headers,
75
+ },
76
+ `ai-sdk/deepgram/${VERSION}`,
77
+ );
78
+
79
+ const createTranscriptionModel = (modelId: DeepgramTranscriptionModelId) =>
80
+ new DeepgramTranscriptionModel(modelId, {
81
+ provider: `deepgram.transcription`,
82
+ url: ({ path }) => `https://api.deepgram.com${path}`,
83
+ headers: getHeaders,
84
+ fetch: options.fetch,
85
+ });
86
+
87
+ const createSpeechModel = (modelId: DeepgramSpeechModelId) =>
88
+ new DeepgramSpeechModel(modelId, {
89
+ provider: `deepgram.speech`,
90
+ url: ({ path }) => `https://api.deepgram.com${path}`,
91
+ headers: getHeaders,
92
+ fetch: options.fetch,
93
+ });
94
+
95
+ const provider = function (modelId: DeepgramTranscriptionModelId) {
96
+ return {
97
+ transcription: createTranscriptionModel(modelId),
98
+ };
99
+ };
100
+
101
+ provider.specificationVersion = 'v3' as const;
102
+ provider.transcription = createTranscriptionModel;
103
+ provider.transcriptionModel = createTranscriptionModel;
104
+ provider.speech = createSpeechModel;
105
+ provider.speechModel = createSpeechModel;
106
+
107
+ // Required ProviderV3 methods that are not supported
108
+ provider.languageModel = (modelId: string) => {
109
+ throw new NoSuchModelError({
110
+ modelId,
111
+ modelType: 'languageModel',
112
+ message: 'Deepgram does not provide language models',
113
+ });
114
+ };
115
+
116
+ provider.embeddingModel = (modelId: string) => {
117
+ throw new NoSuchModelError({
118
+ modelId,
119
+ modelType: 'embeddingModel',
120
+ message: 'Deepgram does not provide text embedding models',
121
+ });
122
+ };
123
+ provider.textEmbeddingModel = provider.embeddingModel;
124
+
125
+ provider.imageModel = (modelId: string) => {
126
+ throw new NoSuchModelError({
127
+ modelId,
128
+ modelType: 'imageModel',
129
+ message: 'Deepgram does not provide image models',
130
+ });
131
+ };
132
+
133
+ return provider as DeepgramProvider;
134
+ }
135
+
136
+ /**
137
+ Default Deepgram provider instance.
138
+ */
139
+ export const deepgram = createDeepgram();
@@ -0,0 +1,15 @@
1
+ export type DeepgramSpeechAPITypes = {
2
+ // Request body
3
+ text: string;
4
+
5
+ // Query parameters (these are set via query params, not body)
6
+ model?: string;
7
+ encoding?: string;
8
+ sample_rate?: number;
9
+ bit_rate?: number | string;
10
+ container?: string;
11
+ callback?: string;
12
+ callback_method?: 'POST' | 'PUT';
13
+ mip_opt_out?: boolean;
14
+ tag?: string | string[];
15
+ };
@@ -0,0 +1,355 @@
1
+ import { createTestServer } from '@ai-sdk/test-server/with-vitest';
2
+ import { createDeepgram } from './deepgram-provider';
3
+ import { DeepgramSpeechModel } from './deepgram-speech-model';
4
+ import { describe, it, expect, vi } from 'vitest';
5
+
6
+ vi.mock('./version', () => ({
7
+ VERSION: '0.0.0-test',
8
+ }));
9
+
10
+ const provider = createDeepgram({ apiKey: 'test-api-key' });
11
+ const model = provider.speech('aura-2-helena-en');
12
+
13
+ const server = createTestServer({
14
+ 'https://api.deepgram.com/v1/speak': {},
15
+ });
16
+
17
+ describe('doGenerate', () => {
18
+ function prepareAudioResponse({
19
+ headers,
20
+ }: {
21
+ headers?: Record<string, string>;
22
+ } = {}) {
23
+ const audioBuffer = new Uint8Array(100); // Mock audio data
24
+ server.urls['https://api.deepgram.com/v1/speak'].response = {
25
+ type: 'binary',
26
+ headers: {
27
+ 'content-type': 'audio/mp3',
28
+ ...headers,
29
+ },
30
+ body: Buffer.from(audioBuffer),
31
+ };
32
+ return audioBuffer;
33
+ }
34
+
35
+ it('should pass the model and text', async () => {
36
+ prepareAudioResponse();
37
+
38
+ await model.doGenerate({
39
+ text: 'Hello, welcome to Deepgram!',
40
+ });
41
+
42
+ expect(await server.calls[0].requestBodyJson).toMatchObject({
43
+ text: 'Hello, welcome to Deepgram!',
44
+ });
45
+
46
+ const url = new URL(server.calls[0].requestUrl);
47
+ expect(url.searchParams.get('model')).toBe('aura-2-helena-en');
48
+ });
49
+
50
+ it('should pass headers', async () => {
51
+ prepareAudioResponse();
52
+
53
+ const provider = createDeepgram({
54
+ apiKey: 'test-api-key',
55
+ headers: {
56
+ 'Custom-Provider-Header': 'provider-header-value',
57
+ },
58
+ });
59
+
60
+ await provider.speech('aura-2-helena-en').doGenerate({
61
+ text: 'Hello, welcome to Deepgram!',
62
+ headers: {
63
+ 'Custom-Request-Header': 'request-header-value',
64
+ },
65
+ });
66
+
67
+ expect(server.calls[0].requestHeaders).toMatchObject({
68
+ authorization: 'Token test-api-key',
69
+ 'content-type': 'application/json',
70
+ 'custom-provider-header': 'provider-header-value',
71
+ 'custom-request-header': 'request-header-value',
72
+ });
73
+
74
+ expect(server.calls[0].requestUserAgent).toContain(
75
+ `ai-sdk/deepgram/0.0.0-test`,
76
+ );
77
+ });
78
+
79
+ it('should pass query parameters for model', async () => {
80
+ prepareAudioResponse();
81
+
82
+ await model.doGenerate({
83
+ text: 'Hello, welcome to Deepgram!',
84
+ });
85
+
86
+ const url = new URL(server.calls[0].requestUrl);
87
+ expect(url.searchParams.get('model')).toBe('aura-2-helena-en');
88
+ });
89
+
90
+ it('should map outputFormat to encoding/container', async () => {
91
+ prepareAudioResponse();
92
+
93
+ await model.doGenerate({
94
+ text: 'Hello, welcome to Deepgram!',
95
+ outputFormat: 'wav',
96
+ });
97
+
98
+ const url = new URL(server.calls[0].requestUrl);
99
+ expect(url.searchParams.get('container')).toBe('wav');
100
+ expect(url.searchParams.get('encoding')).toBe('linear16');
101
+ });
102
+
103
+ it('should pass provider options', async () => {
104
+ prepareAudioResponse();
105
+
106
+ await model.doGenerate({
107
+ text: 'Hello, welcome to Deepgram!',
108
+ providerOptions: {
109
+ deepgram: {
110
+ encoding: 'mp3',
111
+ bitRate: 48000,
112
+ container: 'wav',
113
+ callback: 'https://example.com/callback',
114
+ callbackMethod: 'POST',
115
+ mipOptOut: true,
116
+ tag: 'test-tag',
117
+ },
118
+ },
119
+ });
120
+
121
+ const url = new URL(server.calls[0].requestUrl);
122
+ expect(url.searchParams.get('encoding')).toBe('mp3');
123
+ expect(url.searchParams.get('bit_rate')).toBe('48000');
124
+ // mp3 doesn't support container, so it should be removed
125
+ expect(url.searchParams.get('container')).toBeNull();
126
+ expect(url.searchParams.get('callback')).toBe(
127
+ 'https://example.com/callback',
128
+ );
129
+ expect(url.searchParams.get('callback_method')).toBe('POST');
130
+ expect(url.searchParams.get('mip_opt_out')).toBe('true');
131
+ expect(url.searchParams.get('tag')).toBe('test-tag');
132
+ });
133
+
134
+ it('should handle array tag', async () => {
135
+ prepareAudioResponse();
136
+
137
+ await model.doGenerate({
138
+ text: 'Hello, welcome to Deepgram!',
139
+ providerOptions: {
140
+ deepgram: {
141
+ tag: ['tag1', 'tag2'],
142
+ },
143
+ },
144
+ });
145
+
146
+ const url = new URL(server.calls[0].requestUrl);
147
+ expect(url.searchParams.get('tag')).toBe('tag1,tag2');
148
+ });
149
+
150
+ it('should return audio data', async () => {
151
+ const audio = new Uint8Array(100); // Mock audio data
152
+ prepareAudioResponse({
153
+ headers: {
154
+ 'x-request-id': 'test-request-id',
155
+ },
156
+ });
157
+
158
+ const result = await model.doGenerate({
159
+ text: 'Hello, welcome to Deepgram!',
160
+ });
161
+
162
+ expect(result.audio).toStrictEqual(audio);
163
+ });
164
+
165
+ it('should include response data with timestamp, modelId and headers', async () => {
166
+ prepareAudioResponse({
167
+ headers: {
168
+ 'x-request-id': 'test-request-id',
169
+ },
170
+ });
171
+
172
+ const testDate = new Date(0);
173
+ const customModel = new DeepgramSpeechModel('aura-2-helena-en', {
174
+ provider: 'test-provider',
175
+ url: () => 'https://api.deepgram.com/v1/speak',
176
+ headers: () => ({}),
177
+ _internal: {
178
+ currentDate: () => testDate,
179
+ },
180
+ });
181
+
182
+ const result = await customModel.doGenerate({
183
+ text: 'Hello, welcome to Deepgram!',
184
+ });
185
+
186
+ expect(result.response).toMatchObject({
187
+ timestamp: testDate,
188
+ modelId: 'aura-2-helena-en',
189
+ headers: {
190
+ 'content-type': 'audio/mp3',
191
+ 'x-request-id': 'test-request-id',
192
+ },
193
+ });
194
+ });
195
+
196
+ it('should warn about unsupported voice parameter', async () => {
197
+ prepareAudioResponse();
198
+
199
+ const result = await model.doGenerate({
200
+ text: 'Hello, welcome to Deepgram!',
201
+ voice: 'different-voice',
202
+ });
203
+
204
+ expect(result.warnings).toMatchInlineSnapshot(`
205
+ [
206
+ {
207
+ "details": "Deepgram TTS models embed the voice in the model ID. The voice parameter "different-voice" was ignored. Use the model ID to select a voice (e.g., "aura-2-helena-en").",
208
+ "feature": "voice",
209
+ "type": "unsupported",
210
+ },
211
+ ]
212
+ `);
213
+ });
214
+
215
+ it('should warn about unsupported speed parameter', async () => {
216
+ prepareAudioResponse();
217
+
218
+ const result = await model.doGenerate({
219
+ text: 'Hello, welcome to Deepgram!',
220
+ speed: 1.5,
221
+ });
222
+
223
+ expect(result.warnings).toMatchInlineSnapshot(`
224
+ [
225
+ {
226
+ "details": "Deepgram TTS REST API does not support speed adjustment. Speed parameter was ignored.",
227
+ "feature": "speed",
228
+ "type": "unsupported",
229
+ },
230
+ ]
231
+ `);
232
+ });
233
+
234
+ it('should warn about unsupported language parameter', async () => {
235
+ prepareAudioResponse();
236
+
237
+ const result = await model.doGenerate({
238
+ text: 'Hello, welcome to Deepgram!',
239
+ language: 'en',
240
+ });
241
+
242
+ expect(result.warnings).toMatchInlineSnapshot(`
243
+ [
244
+ {
245
+ "details": "Deepgram TTS models are language-specific via the model ID. Language parameter "en" was ignored. Select a model with the appropriate language suffix (e.g., "-en" for English).",
246
+ "feature": "language",
247
+ "type": "unsupported",
248
+ },
249
+ ]
250
+ `);
251
+ });
252
+
253
+ it('should warn about unsupported instructions parameter', async () => {
254
+ prepareAudioResponse();
255
+
256
+ const result = await model.doGenerate({
257
+ text: 'Hello, welcome to Deepgram!',
258
+ instructions: 'Speak slowly',
259
+ });
260
+
261
+ expect(result.warnings).toMatchInlineSnapshot(`
262
+ [
263
+ {
264
+ "details": "Deepgram TTS REST API does not support instructions. Instructions parameter was ignored.",
265
+ "feature": "instructions",
266
+ "type": "unsupported",
267
+ },
268
+ ]
269
+ `);
270
+ });
271
+
272
+ it('should include request body in response', async () => {
273
+ prepareAudioResponse();
274
+
275
+ const result = await model.doGenerate({
276
+ text: 'Hello, welcome to Deepgram!',
277
+ });
278
+
279
+ expect(result.request?.body).toBe(
280
+ JSON.stringify({ text: 'Hello, welcome to Deepgram!' }),
281
+ );
282
+ });
283
+
284
+ it('should clean up incompatible parameters when encoding changes via providerOptions', async () => {
285
+ prepareAudioResponse();
286
+
287
+ // Test case 1: outputFormat sets sample_rate, encoding changed to mp3 (fixed sample rate)
288
+ await model.doGenerate({
289
+ text: 'Hello, welcome to Deepgram!',
290
+ outputFormat: 'linear16_16000', // Sets: encoding=linear16, sample_rate=16000
291
+ providerOptions: {
292
+ deepgram: {
293
+ encoding: 'mp3', // Changes encoding to mp3
294
+ },
295
+ },
296
+ });
297
+
298
+ const url1 = new URL(server.calls[0].requestUrl);
299
+ expect(url1.searchParams.get('encoding')).toBe('mp3');
300
+ expect(url1.searchParams.get('sample_rate')).toBeNull(); // Should be removed
301
+
302
+ // Test case 2: outputFormat sets container for linear16, encoding changed to opus
303
+ await model.doGenerate({
304
+ text: 'Hello, welcome to Deepgram!',
305
+ outputFormat: 'linear16_16000', // Sets: encoding=linear16, container=wav
306
+ providerOptions: {
307
+ deepgram: {
308
+ encoding: 'opus', // Changes encoding to opus
309
+ },
310
+ },
311
+ });
312
+
313
+ const url2 = new URL(server.calls[1].requestUrl);
314
+ expect(url2.searchParams.get('encoding')).toBe('opus');
315
+ expect(url2.searchParams.get('container')).toBe('ogg'); // Should be ogg, not wav
316
+ expect(url2.searchParams.get('sample_rate')).toBeNull(); // Should be removed
317
+
318
+ // Test case 3: outputFormat sets bit_rate, encoding changed to linear16 (no bitrate support)
319
+ await model.doGenerate({
320
+ text: 'Hello, welcome to Deepgram!',
321
+ outputFormat: 'mp3', // Sets: encoding=mp3
322
+ providerOptions: {
323
+ deepgram: {
324
+ encoding: 'linear16', // Changes encoding to linear16
325
+ bitRate: 48000, // Try to set bitrate
326
+ },
327
+ },
328
+ });
329
+
330
+ const url3 = new URL(server.calls[2].requestUrl);
331
+ expect(url3.searchParams.get('encoding')).toBe('linear16');
332
+ expect(url3.searchParams.get('bit_rate')).toBeNull(); // Should be removed
333
+ });
334
+
335
+ it('should clean up incompatible parameters when container changes encoding implicitly', async () => {
336
+ prepareAudioResponse();
337
+
338
+ // Test case: outputFormat sets sample_rate, container changes encoding to opus
339
+ await model.doGenerate({
340
+ text: 'Hello, welcome to Deepgram!',
341
+ outputFormat: 'linear16_16000', // Sets: encoding=linear16, sample_rate=16000
342
+ providerOptions: {
343
+ deepgram: {
344
+ container: 'ogg', // Changes encoding to opus implicitly
345
+ },
346
+ },
347
+ });
348
+
349
+ const callIndex = server.calls.length - 1;
350
+ const url = new URL(server.calls[callIndex].requestUrl);
351
+ expect(url.searchParams.get('encoding')).toBe('opus');
352
+ expect(url.searchParams.get('container')).toBe('ogg');
353
+ expect(url.searchParams.get('sample_rate')).toBeNull(); // Should be removed (opus has fixed sample rate)
354
+ });
355
+ });