ai 6.0.293 → 6.0.294

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.
@@ -164,7 +164,7 @@ function detectMediaType({
164
164
  var import_provider_utils2 = require("@ai-sdk/provider-utils");
165
165
 
166
166
  // src/version.ts
167
- var VERSION = true ? "6.0.293" : "0.0.0-test";
167
+ var VERSION = true ? "6.0.294" : "0.0.0-test";
168
168
 
169
169
  // src/util/download/download.ts
170
170
  var download = async ({
@@ -144,7 +144,7 @@ import {
144
144
  } from "@ai-sdk/provider-utils";
145
145
 
146
146
  // src/version.ts
147
- var VERSION = true ? "6.0.293" : "0.0.0-test";
147
+ var VERSION = true ? "6.0.294" : "0.0.0-test";
148
148
 
149
149
  // src/util/download/download.ts
150
150
  var download = async ({
@@ -208,6 +208,7 @@ try {
208
208
  | [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3-turbo` |
209
209
  | [Groq](/providers/ai-sdk-providers/groq#transcription-models) | `whisper-large-v3` |
210
210
  | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `whisper-1` |
211
+ | [Azure Speech](/providers/ai-sdk-providers/azure#mai-transcribe-2) | `mai-transcribe-2` |
211
212
  | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-transcribe` |
212
213
  | [Azure OpenAI](/providers/ai-sdk-providers/azure#transcription-models) | `gpt-4o-mini-transcribe` |
213
214
  | [Rev.ai](/providers/ai-sdk-providers/revai#transcription-models) | `machine` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "6.0.293",
3
+ "version": "6.0.294",
4
4
  "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -45,9 +45,9 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@opentelemetry/api": "^1.9.0",
48
- "@ai-sdk/gateway": "3.0.203",
48
+ "@ai-sdk/gateway": "3.0.204",
49
49
  "@ai-sdk/provider": "3.0.18",
50
- "@ai-sdk/provider-utils": "4.0.55"
50
+ "@ai-sdk/provider-utils": "4.0.56"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@edge-runtime/vm": "^5.0.0",
@@ -58,7 +58,7 @@
58
58
  "tsx": "^4.19.2",
59
59
  "typescript": "5.8.3",
60
60
  "zod": "3.25.76",
61
- "@ai-sdk/google": "3.0.128",
61
+ "@ai-sdk/google": "3.0.129",
62
62
  "@ai-sdk/test-server": "1.0.6",
63
63
  "@vercel/ai-tsconfig": "0.0.0"
64
64
  },
@@ -2,6 +2,10 @@ import type { ServerResponse } from 'node:http';
2
2
 
3
3
  /**
4
4
  * Writes the content of a stream to a server response.
5
+ *
6
+ * When the client disconnects before the stream has been fully written
7
+ * (premature `close`), the stream is cancelled so that upstream resources
8
+ * can be released, and no further chunks are written.
5
9
  */
6
10
  export function writeToServerResponse({
7
11
  response,
@@ -24,22 +28,57 @@ export function writeToServerResponse({
24
28
  }
25
29
 
26
30
  const reader = stream.getReader();
31
+
32
+ // Detect client disconnects. `close` also fires after a regular `end()`;
33
+ // `writableFinished` distinguishes the two cases.
34
+ let clientDisconnected = false;
35
+ let onDisconnect: (() => void) | undefined;
36
+ const handleClose = () => {
37
+ if (response.writableFinished) {
38
+ return;
39
+ }
40
+
41
+ clientDisconnected = true;
42
+ onDisconnect?.();
43
+
44
+ // cancelling the reader resolves a pending read with `done: true`:
45
+ reader.cancel(new Error('Client disconnected.')).catch(() => {});
46
+ };
47
+ response.once('close', handleClose);
48
+
49
+ // The response may have been destroyed before the close listener was
50
+ // registered. Cancel immediately instead of waiting indefinitely for the
51
+ // next stream chunk.
52
+ if (response.destroyed) {
53
+ handleClose();
54
+ }
55
+
27
56
  const read = async () => {
28
57
  try {
29
58
  while (true) {
30
59
  const { done, value } = await reader.read();
31
- if (done) break;
60
+ if (done || clientDisconnected || response.destroyed) break;
32
61
 
33
62
  // Respect backpressure: if write() returns false, wait for 'drain' event
34
63
  const canContinue = response.write(value);
35
64
  if (!canContinue) {
36
65
  await new Promise<void>(resolve => {
66
+ // don't wait for `drain` on a disconnected response:
67
+ onDisconnect = resolve;
37
68
  response.once('drain', resolve);
38
69
  });
70
+ onDisconnect = undefined;
39
71
  }
40
72
  }
41
73
  } finally {
42
- response.end();
74
+ response.off('close', handleClose);
75
+
76
+ if (clientDisconnected || response.destroyed) {
77
+ // release the stream; ending a destroyed response is not possible:
78
+ reader.cancel().catch(() => {});
79
+ } else {
80
+ response.end();
81
+ }
43
82
  }
44
83
  };
45
84