voice-router-dev 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -583,6 +583,12 @@ var Status = {
583
583
  Failed: "Failed"
584
584
  };
585
585
 
586
+ // src/generated/deepgram/schema/manageV1FilterStatusParameter.ts
587
+ var ManageV1FilterStatusParameter = {
588
+ succeeded: "succeeded",
589
+ failed: "failed"
590
+ };
591
+
586
592
  // src/constants.ts
587
593
  var DeepgramEncoding = ListenV1EncodingParameter;
588
594
  var DeepgramRedact = ListenV1RedactParameterOneOfItem;
@@ -1880,6 +1886,12 @@ var preRecordedControllerGetPreRecordedJobV2 = (id, options) => {
1880
1886
  var preRecordedControllerDeletePreRecordedJobV2 = (id, options) => {
1881
1887
  return import_axios.default.delete(`/v2/pre-recorded/${id}`, options);
1882
1888
  };
1889
+ var preRecordedControllerGetAudioV2 = (id, options) => {
1890
+ return import_axios.default.get(`/v2/pre-recorded/${id}/file`, {
1891
+ responseType: "blob",
1892
+ ...options
1893
+ });
1894
+ };
1883
1895
  var transcriptionControllerListV2 = (params, options) => {
1884
1896
  return import_axios.default.get("/v2/transcription", {
1885
1897
  ...options,
@@ -1895,6 +1907,12 @@ var streamingControllerInitStreamingSessionV2 = (streamingRequest, params, optio
1895
1907
  var streamingControllerDeleteStreamingJobV2 = (id, options) => {
1896
1908
  return import_axios.default.delete(`/v2/live/${id}`, options);
1897
1909
  };
1910
+ var streamingControllerGetAudioV2 = (id, options) => {
1911
+ return import_axios.default.get(`/v2/live/${id}/file`, {
1912
+ responseType: "blob",
1913
+ ...options
1914
+ });
1915
+ };
1898
1916
 
1899
1917
  // src/adapters/gladia-adapter.ts
1900
1918
  var GladiaAdapter = class extends BaseAdapter {
@@ -1913,7 +1931,9 @@ var GladiaAdapter = class extends BaseAdapter {
1913
1931
  piiRedaction: false,
1914
1932
  // Gladia doesn't have PII redaction in their API
1915
1933
  listTranscripts: true,
1916
- deleteTranscript: true
1934
+ deleteTranscript: true,
1935
+ getAudioFile: true
1936
+ // Gladia stores and allows downloading original audio files
1917
1937
  };
1918
1938
  this.baseUrl = "https://api.gladia.io";
1919
1939
  }
@@ -2128,6 +2148,10 @@ var GladiaAdapter = class extends BaseAdapter {
2128
2148
  utterances: this.extractUtterances(transcription),
2129
2149
  summary: result?.summarization?.results || void 0,
2130
2150
  metadata: {
2151
+ sourceAudioUrl: response.file?.source ?? void 0,
2152
+ audioFileAvailable: this.capabilities.getAudioFile ?? false,
2153
+ filename: response.file?.filename ?? void 0,
2154
+ audioDuration: response.file?.audio_duration ?? void 0,
2131
2155
  requestParams: response.request_params
2132
2156
  },
2133
2157
  createdAt: response.created_at,
@@ -2246,6 +2270,72 @@ var GladiaAdapter = class extends BaseAdapter {
2246
2270
  throw error;
2247
2271
  }
2248
2272
  }
2273
+ /**
2274
+ * Download the original audio file from a transcription
2275
+ *
2276
+ * Gladia stores the audio files used for transcription and allows downloading them.
2277
+ * This works for both pre-recorded and streaming (live) transcriptions.
2278
+ *
2279
+ * @param transcriptId - The ID of the transcript/job
2280
+ * @param jobType - Type of job: 'pre-recorded' or 'streaming' (defaults to 'pre-recorded')
2281
+ * @returns Promise with the audio file as a Blob, or error
2282
+ *
2283
+ * @example Download audio from a pre-recorded transcription
2284
+ * ```typescript
2285
+ * const result = await adapter.getAudioFile('abc123');
2286
+ * if (result.success && result.data) {
2287
+ * // Save to file (Node.js)
2288
+ * const buffer = Buffer.from(await result.data.arrayBuffer());
2289
+ * fs.writeFileSync('audio.mp3', buffer);
2290
+ *
2291
+ * // Or create download URL (browser)
2292
+ * const url = URL.createObjectURL(result.data);
2293
+ * }
2294
+ * ```
2295
+ *
2296
+ * @example Download audio from a live/streaming session
2297
+ * ```typescript
2298
+ * const result = await adapter.getAudioFile('stream-456', 'streaming');
2299
+ * if (result.success) {
2300
+ * console.log('Audio file size:', result.data?.size);
2301
+ * }
2302
+ * ```
2303
+ *
2304
+ * @see https://docs.gladia.io/
2305
+ */
2306
+ async getAudioFile(transcriptId, jobType = "pre-recorded") {
2307
+ this.validateConfig();
2308
+ try {
2309
+ let response;
2310
+ if (jobType === "streaming") {
2311
+ response = await streamingControllerGetAudioV2(transcriptId, this.getAxiosConfig());
2312
+ } else {
2313
+ response = await preRecordedControllerGetAudioV2(transcriptId, this.getAxiosConfig());
2314
+ }
2315
+ return {
2316
+ success: true,
2317
+ data: response.data
2318
+ };
2319
+ } catch (error) {
2320
+ const err = error;
2321
+ if (err.response?.status === 404) {
2322
+ return {
2323
+ success: false,
2324
+ error: {
2325
+ code: "NOT_FOUND",
2326
+ message: `Audio file not found for transcript ${transcriptId}`
2327
+ }
2328
+ };
2329
+ }
2330
+ return {
2331
+ success: false,
2332
+ error: {
2333
+ code: "DOWNLOAD_ERROR",
2334
+ message: err.message || "Failed to download audio file"
2335
+ }
2336
+ };
2337
+ }
2338
+ }
2249
2339
  /**
2250
2340
  * List recent transcriptions with filtering
2251
2341
  *
@@ -2350,6 +2440,7 @@ var GladiaAdapter = class extends BaseAdapter {
2350
2440
  const id = preRecorded.id || streaming.id;
2351
2441
  const status = normalizeStatus(preRecorded.status || streaming.status, "gladia");
2352
2442
  const text = preRecorded.result?.transcription?.full_transcript || "";
2443
+ const file = preRecorded.file;
2353
2444
  return {
2354
2445
  success: status !== "error",
2355
2446
  provider: this.name,
@@ -2357,7 +2448,13 @@ var GladiaAdapter = class extends BaseAdapter {
2357
2448
  id,
2358
2449
  text,
2359
2450
  status,
2451
+ duration: file?.audio_duration ?? void 0,
2360
2452
  metadata: {
2453
+ sourceAudioUrl: file?.source ?? void 0,
2454
+ audioFileAvailable: this.capabilities.getAudioFile ?? false,
2455
+ filename: file?.filename ?? void 0,
2456
+ audioDuration: file?.audio_duration ?? void 0,
2457
+ numberOfChannels: file?.number_of_channels ?? void 0,
2361
2458
  createdAt: preRecorded.created_at || streaming.created_at,
2362
2459
  completedAt: preRecorded.completed_at || streaming.completed_at || void 0,
2363
2460
  kind: isLive ? "live" : "pre-recorded",
@@ -2367,7 +2464,8 @@ var GladiaAdapter = class extends BaseAdapter {
2367
2464
  error: preRecorded.error_code || streaming.error_code ? {
2368
2465
  code: (preRecorded.error_code || streaming.error_code)?.toString() || "ERROR",
2369
2466
  message: "Transcription failed"
2370
- } : void 0
2467
+ } : void 0,
2468
+ raw: item
2371
2469
  };
2372
2470
  }
2373
2471
  /**
@@ -3518,8 +3616,10 @@ var AssemblyAIAdapter = class extends BaseAdapter {
3518
3616
  text: "",
3519
3617
  // List items don't include full text
3520
3618
  status: item.status,
3619
+ // Note: audio_duration is NOT available in TranscriptListItem (only in full Transcript)
3521
3620
  metadata: {
3522
- audioUrl: item.audio_url,
3621
+ sourceAudioUrl: item.audio_url,
3622
+ audioFileAvailable: this.capabilities.getAudioFile ?? false,
3523
3623
  createdAt: item.created,
3524
3624
  completedAt: item.completed || void 0,
3525
3625
  resourceUrl: item.resource_url
@@ -3528,7 +3628,8 @@ var AssemblyAIAdapter = class extends BaseAdapter {
3528
3628
  error: item.error ? {
3529
3629
  code: "TRANSCRIPTION_ERROR",
3530
3630
  message: item.error
3531
- } : void 0
3631
+ } : void 0,
3632
+ raw: item
3532
3633
  };
3533
3634
  }
3534
3635
  /**
@@ -3638,7 +3739,8 @@ var AssemblyAIAdapter = class extends BaseAdapter {
3638
3739
  utterances: this.extractUtterances(response),
3639
3740
  summary: response.summary || void 0,
3640
3741
  metadata: {
3641
- audioUrl: response.audio_url
3742
+ sourceAudioUrl: response.audio_url,
3743
+ audioFileAvailable: this.capabilities.getAudioFile ?? false
3642
3744
  }
3643
3745
  },
3644
3746
  // Extended data - fully typed from OpenAPI specs
@@ -4083,6 +4185,16 @@ function createAssemblyAIAdapter(config) {
4083
4185
  // src/adapters/deepgram-adapter.ts
4084
4186
  var import_axios3 = __toESM(require("axios"));
4085
4187
  var import_ws3 = __toESM(require("ws"));
4188
+
4189
+ // src/generated/deepgram/schema/manageV1FilterEndpointParameter.ts
4190
+ var ManageV1FilterEndpointParameter = {
4191
+ listen: "listen",
4192
+ read: "read",
4193
+ speak: "speak",
4194
+ agent: "agent"
4195
+ };
4196
+
4197
+ // src/adapters/deepgram-adapter.ts
4086
4198
  var DeepgramAdapter = class extends BaseAdapter {
4087
4199
  constructor() {
4088
4200
  super(...arguments);
@@ -4097,8 +4209,8 @@ var DeepgramAdapter = class extends BaseAdapter {
4097
4209
  sentimentAnalysis: true,
4098
4210
  entityDetection: true,
4099
4211
  piiRedaction: true,
4100
- listTranscripts: false,
4101
- // Deepgram doesn't store transcripts
4212
+ listTranscripts: true,
4213
+ // Via request history API (requires projectId)
4102
4214
  deleteTranscript: false
4103
4215
  };
4104
4216
  this.baseUrl = "https://api.deepgram.com/v1";
@@ -4106,6 +4218,7 @@ var DeepgramAdapter = class extends BaseAdapter {
4106
4218
  }
4107
4219
  initialize(config) {
4108
4220
  super.initialize(config);
4221
+ this.projectId = config.projectId;
4109
4222
  this.client = import_axios3.default.create({
4110
4223
  baseURL: config.baseUrl || this.baseUrl,
4111
4224
  timeout: config.timeout || 6e4,
@@ -4190,23 +4303,66 @@ var DeepgramAdapter = class extends BaseAdapter {
4190
4303
  /**
4191
4304
  * Get transcription result by ID
4192
4305
  *
4193
- * Note: Deepgram processes synchronously, so this method is primarily
4194
- * for retrieving cached results if you've stored the request ID.
4195
- * The initial transcribe() call already returns complete results.
4306
+ * Retrieves a previous transcription from Deepgram's request history.
4196
4307
  *
4197
- * @param transcriptId - Request ID from Deepgram
4198
- * @returns Normalized transcription response
4308
+ * Unlike the list endpoint, getting a single request DOES include the full
4309
+ * transcript response. Requires `projectId` to be set during initialization.
4310
+ *
4311
+ * @param transcriptId - Request ID from a previous transcription
4312
+ * @returns Full transcript response including text, words, and metadata
4313
+ *
4314
+ * @example Get a transcript by request ID
4315
+ * ```typescript
4316
+ * const adapter = new DeepgramAdapter()
4317
+ * adapter.initialize({
4318
+ * apiKey: process.env.DEEPGRAM_API_KEY,
4319
+ * projectId: process.env.DEEPGRAM_PROJECT_ID
4320
+ * })
4321
+ *
4322
+ * const result = await adapter.getTranscript('abc123-request-id')
4323
+ * if (result.success) {
4324
+ * console.log(result.data?.text)
4325
+ * console.log(result.data?.words)
4326
+ * }
4327
+ * ```
4328
+ *
4329
+ * @see https://developers.deepgram.com/reference/get-request
4199
4330
  */
4200
4331
  async getTranscript(transcriptId) {
4201
4332
  this.validateConfig();
4202
- return {
4203
- success: false,
4204
- provider: this.name,
4205
- error: {
4206
- code: "NOT_SUPPORTED",
4207
- message: "Deepgram returns transcription results immediately. Store the response from transcribe() instead of using getTranscript()."
4333
+ if (!this.projectId) {
4334
+ return {
4335
+ success: false,
4336
+ provider: this.name,
4337
+ error: {
4338
+ code: "MISSING_PROJECT_ID",
4339
+ message: "Deepgram getTranscript requires projectId. Initialize with: { apiKey, projectId }"
4340
+ }
4341
+ };
4342
+ }
4343
+ try {
4344
+ const response = await this.client.get(
4345
+ `/projects/${this.projectId}/requests/${transcriptId}`
4346
+ );
4347
+ const request = response.data.request;
4348
+ if (!request) {
4349
+ return {
4350
+ success: false,
4351
+ provider: this.name,
4352
+ error: {
4353
+ code: "NOT_FOUND",
4354
+ message: `Request ${transcriptId} not found`
4355
+ }
4356
+ };
4208
4357
  }
4209
- };
4358
+ const transcriptResponse = request.response;
4359
+ if (!transcriptResponse) {
4360
+ return this.normalizeRequestItem(request);
4361
+ }
4362
+ return this.normalizeResponse(transcriptResponse);
4363
+ } catch (error) {
4364
+ return this.createErrorResponse(error);
4365
+ }
4210
4366
  }
4211
4367
  /**
4212
4368
  * Build Deepgram transcription parameters from unified options
@@ -4776,6 +4932,133 @@ var DeepgramAdapter = class extends BaseAdapter {
4776
4932
  }
4777
4933
  }
4778
4934
  }
4935
+ /**
4936
+ * List recent transcription requests from Deepgram's request history
4937
+ *
4938
+ * **Important:** Deepgram processes synchronously and doesn't store transcript content.
4939
+ * This method returns request metadata (IDs, timestamps, status) but NOT the actual
4940
+ * transcript text. Use this for auditing, billing analysis, or request tracking.
4941
+ *
4942
+ * Requires `projectId` to be set during initialization.
4943
+ *
4944
+ * @param options - Filtering and pagination options
4945
+ * @param options.limit - Maximum number of requests (default 10, max 1000)
4946
+ * @param options.status - Filter by status: 'succeeded' or 'failed'
4947
+ * @param options.afterDate - Start date (YYYY-MM-DD or ISO 8601)
4948
+ * @param options.beforeDate - End date (YYYY-MM-DD or ISO 8601)
4949
+ * @param options.deepgram - Provider-specific params (page, request_id, etc.)
4950
+ * @returns List of transcription request metadata
4951
+ *
4952
+ * @example List recent transcription requests
4953
+ * ```typescript
4954
+ * const adapter = new DeepgramAdapter()
4955
+ * adapter.initialize({
4956
+ * apiKey: process.env.DEEPGRAM_API_KEY,
4957
+ * projectId: process.env.DEEPGRAM_PROJECT_ID
4958
+ * })
4959
+ *
4960
+ * const { transcripts, hasMore } = await adapter.listTranscripts({
4961
+ * limit: 50,
4962
+ * status: 'succeeded'
4963
+ * })
4964
+ *
4965
+ * transcripts.forEach(t => {
4966
+ * console.log(t.data?.id, t.data?.metadata?.createdAt)
4967
+ * })
4968
+ * ```
4969
+ *
4970
+ * @see https://developers.deepgram.com/reference/get-all-requests
4971
+ */
4972
+ async listTranscripts(options) {
4973
+ this.validateConfig();
4974
+ if (!this.projectId) {
4975
+ return {
4976
+ transcripts: [
4977
+ {
4978
+ success: false,
4979
+ provider: this.name,
4980
+ error: {
4981
+ code: "MISSING_PROJECT_ID",
4982
+ message: "Deepgram listTranscripts requires projectId. Initialize with: { apiKey, projectId }"
4983
+ }
4984
+ }
4985
+ ],
4986
+ hasMore: false
4987
+ };
4988
+ }
4989
+ try {
4990
+ const params = {
4991
+ // Filter to only transcription requests (listen endpoint)
4992
+ endpoint: ManageV1FilterEndpointParameter.listen,
4993
+ ...options?.deepgram
4994
+ };
4995
+ if (options?.limit) {
4996
+ params.limit = options.limit;
4997
+ }
4998
+ if (options?.afterDate) {
4999
+ params.start = options.afterDate;
5000
+ }
5001
+ if (options?.beforeDate) {
5002
+ params.end = options.beforeDate;
5003
+ }
5004
+ if (options?.status) {
5005
+ const statusMap = {
5006
+ completed: ManageV1FilterStatusParameter.succeeded,
5007
+ succeeded: ManageV1FilterStatusParameter.succeeded,
5008
+ error: ManageV1FilterStatusParameter.failed,
5009
+ failed: ManageV1FilterStatusParameter.failed
5010
+ };
5011
+ params.status = statusMap[options.status.toLowerCase()];
5012
+ }
5013
+ const response = await this.client.get(
5014
+ `/projects/${this.projectId}/requests`,
5015
+ { params }
5016
+ );
5017
+ const data = response.data;
5018
+ const transcripts = (data.requests || []).map(
5019
+ (item) => this.normalizeRequestItem(item)
5020
+ );
5021
+ return {
5022
+ transcripts,
5023
+ hasMore: (data.page || 1) * (data.limit || 10) < (data.requests?.length || 0)
5024
+ };
5025
+ } catch (error) {
5026
+ return {
5027
+ transcripts: [this.createErrorResponse(error)],
5028
+ hasMore: false
5029
+ };
5030
+ }
5031
+ }
5032
+ /**
5033
+ * Normalize a Deepgram request history item to unified format
5034
+ */
5035
+ normalizeRequestItem(item) {
5036
+ const isSuccess = (item.code || 0) < 400;
5037
+ return {
5038
+ success: isSuccess,
5039
+ provider: this.name,
5040
+ data: {
5041
+ id: item.request_id || "",
5042
+ text: "",
5043
+ // Deepgram doesn't store transcript content in request history
5044
+ status: isSuccess ? "completed" : "error",
5045
+ metadata: {
5046
+ audioFileAvailable: this.capabilities.getAudioFile ?? false,
5047
+ createdAt: item.created,
5048
+ apiPath: item.path,
5049
+ apiKeyId: item.api_key_id,
5050
+ deployment: item.deployment,
5051
+ callbackUrl: item.callback,
5052
+ responseCode: item.code
5053
+ }
5054
+ },
5055
+ error: !isSuccess ? {
5056
+ code: "REQUEST_FAILED",
5057
+ message: `Request failed with status code ${item.code}`
5058
+ } : void 0,
5059
+ raw: item
5060
+ };
5061
+ }
4779
5062
  };
4780
5063
  function createDeepgramAdapter(config) {
4781
5064
  const adapter = new DeepgramAdapter();
@@ -5080,8 +5363,12 @@ var AzureSTTAdapter = class extends BaseAdapter {
5080
5363
  // List items don't include full text
5081
5364
  status,
5082
5365
  language: item.locale,
5366
+ // Note: contentUrls is write-only per Azure API docs (not returned in list response)
5367
+ // Note: duration is not available in Transcription list item
5083
5368
  metadata: {
5369
+ audioFileAvailable: this.capabilities.getAudioFile ?? false,
5084
5370
  displayName: item.displayName,
5371
+ description: item.description || void 0,
5085
5372
  createdAt: item.createdDateTime,
5086
5373
  lastActionAt: item.lastActionDateTime,
5087
5374
  filesUrl: item.links?.files
@@ -5090,7 +5377,8 @@ var AzureSTTAdapter = class extends BaseAdapter {
5090
5377
  error: status === "error" ? {
5091
5378
  code: "TRANSCRIPTION_ERROR",
5092
5379
  message: item.properties?.error?.message || "Transcription failed"
5093
- } : void 0
5380
+ } : void 0,
5381
+ raw: item
5094
5382
  };
5095
5383
  }
5096
5384
  /**