ai 7.0.22 → 7.0.25

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.
@@ -15,6 +15,7 @@ import type { TranscriptionModel } from '../types/transcription-model';
15
15
  import type { TranscriptionModelResponseMetadata } from '../types/transcription-model-response-metadata';
16
16
  import type { Warning } from '../types/warning';
17
17
  import { asAsyncIterableStream } from '../util/async-iterable-stream';
18
+ import { mergeAbortSignals } from '../util/merge-abort-signals';
18
19
  import { VERSION } from '../version';
19
20
  import type {
20
21
  StreamTranscriptionResult,
@@ -113,9 +114,10 @@ export function streamTranscribe({
113
114
  message:
114
115
  `The ${resolvedModel.provider} model "${resolvedModel.modelId}" does not support streaming transcription.` +
115
116
  (typeof model === 'string'
116
- ? ' String model IDs resolve through the global provider (AI Gateway by default),' +
117
- ' which does not support streaming transcription yet.' +
118
- " Pass a provider model instance instead, e.g. openai.transcription('gpt-realtime-whisper')."
117
+ ? ' String model IDs resolve through the global provider (AI Gateway by default).' +
118
+ ' If that provider does not support streaming transcription, pass a provider model' +
119
+ " instance instead (e.g. openai.transcription('gpt-realtime-whisper'))" +
120
+ ' or upgrade @ai-sdk/gateway to a version with streaming transcription support.'
119
121
  : ''),
120
122
  });
121
123
  }
@@ -253,7 +255,8 @@ export function streamTranscribe({
253
255
  audio,
254
256
  inputAudioFormat,
255
257
  providerOptions,
256
- abortSignal,
258
+ // merged so cancelling fullStream also aborts a still-pending doStream
259
+ abortSignal: mergeAbortSignals(abortSignal, pipeAbortController.signal),
257
260
  headers: headersWithUserAgent,
258
261
  includeRawChunks,
259
262
  });
@@ -271,6 +274,12 @@ export function streamTranscribe({
271
274
  const reason =
272
275
  error ?? new Error('Transcription stream was cancelled or errored.');
273
276
  rejectPendingPromises(reason);
277
+ // When `doStream` rejects before the model stream exists (e.g. auth or
278
+ // header resolution failure), nothing has taken ownership of `audio` yet,
279
+ // so cancel it directly — otherwise an upstream producer piping into it
280
+ // hangs forever. When the model did take a reader, `audio` is locked and
281
+ // the cancel rejects, which is fine: the model's cleanup owns it then.
282
+ audio.cancel(reason).catch(() => {});
274
283
  transform.writable.abort(reason).catch(() => {
275
284
  // the writable is already errored when the model stream failed mid-pipe
276
285
  });