ai 6.0.293 → 6.0.295
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 +17 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +48 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +48 -4
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.mjs +1 -1
- package/docs/02-foundations/02-providers-and-models.mdx +1 -0
- package/docs/03-ai-sdk-core/36-transcription.mdx +1 -0
- package/package.json +4 -4
- package/src/ui/chat.ts +36 -7
- package/src/util/write-to-server-response.ts +41 -2
package/dist/internal/index.js
CHANGED
|
@@ -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.
|
|
167
|
+
var VERSION = true ? "6.0.295" : "0.0.0-test";
|
|
168
168
|
|
|
169
169
|
// src/util/download/download.ts
|
|
170
170
|
var download = async ({
|
package/dist/internal/index.mjs
CHANGED
|
@@ -142,6 +142,7 @@ Here are the capabilities of popular models:
|
|
|
142
142
|
| [OpenAI](/providers/ai-sdk-providers/openai) | `gpt-5-chat-latest` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
143
143
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-fable-5-1` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
144
144
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-5-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
145
|
+
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-sonnet-5-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
145
146
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-sonnet-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
146
147
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-fable-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
147
148
|
| [Anthropic](/providers/ai-sdk-providers/anthropic) | `claude-opus-4-8` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
@@ -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.
|
|
3
|
+
"version": "6.0.295",
|
|
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.
|
|
48
|
+
"@ai-sdk/gateway": "3.0.205",
|
|
49
49
|
"@ai-sdk/provider": "3.0.18",
|
|
50
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
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.
|
|
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
|
},
|
package/src/ui/chat.ts
CHANGED
|
@@ -262,6 +262,9 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
262
262
|
private pendingApprovalMessageId: string | undefined;
|
|
263
263
|
private activeResponse: ActiveResponse<UI_MESSAGE> | undefined = undefined;
|
|
264
264
|
private activeResumeRequest: ActiveResumeRequest | undefined = undefined;
|
|
265
|
+
private resumableStreamState:
|
|
266
|
+
| StreamingUIMessageState<UI_MESSAGE>
|
|
267
|
+
| undefined = undefined;
|
|
265
268
|
private jobExecutor = new SerialJobExecutor();
|
|
266
269
|
|
|
267
270
|
constructor({
|
|
@@ -697,6 +700,10 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
697
700
|
trigger: 'submit-message' | 'resume-stream' | 'regenerate-message';
|
|
698
701
|
messageId?: string;
|
|
699
702
|
} & ChatRequestOptions) {
|
|
703
|
+
if (trigger !== 'resume-stream') {
|
|
704
|
+
this.resumableStreamState = undefined;
|
|
705
|
+
}
|
|
706
|
+
|
|
700
707
|
const abortController = new AbortController();
|
|
701
708
|
const activeResumeRequest =
|
|
702
709
|
trigger === 'resume-stream' ? { abortController } : undefined;
|
|
@@ -734,6 +741,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
734
741
|
await reconnect?.cancel().catch(() => {});
|
|
735
742
|
if (isCurrentRequest()) {
|
|
736
743
|
this.setStatus({ status: 'ready' });
|
|
744
|
+
this.resumableStreamState = undefined;
|
|
737
745
|
}
|
|
738
746
|
clearActiveResumeRequest();
|
|
739
747
|
return;
|
|
@@ -741,6 +749,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
741
749
|
|
|
742
750
|
if (reconnect == null) {
|
|
743
751
|
this.setStatus({ status: 'ready' });
|
|
752
|
+
this.resumableStreamState = undefined;
|
|
744
753
|
clearActiveResumeRequest();
|
|
745
754
|
return; // no active stream found, so we do not resume
|
|
746
755
|
}
|
|
@@ -753,6 +762,7 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
753
762
|
) {
|
|
754
763
|
if (isCurrentRequest()) {
|
|
755
764
|
this.setStatus({ status: 'ready' });
|
|
765
|
+
this.resumableStreamState = undefined;
|
|
756
766
|
}
|
|
757
767
|
clearActiveResumeRequest();
|
|
758
768
|
return;
|
|
@@ -794,13 +804,17 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
794
804
|
|
|
795
805
|
try {
|
|
796
806
|
const response = {
|
|
797
|
-
state:
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
807
|
+
state:
|
|
808
|
+
trigger === 'resume-stream' && this.resumableStreamState != null
|
|
809
|
+
? this.resumableStreamState
|
|
810
|
+
: createStreamingUIMessageState({
|
|
811
|
+
lastMessage:
|
|
812
|
+
trigger === 'resume-stream' ||
|
|
813
|
+
trigger === 'regenerate-message'
|
|
814
|
+
? undefined
|
|
815
|
+
: this.state.snapshot(responseMessage),
|
|
816
|
+
messageId: this.generateId(),
|
|
817
|
+
}),
|
|
804
818
|
abortController,
|
|
805
819
|
} as ActiveResponse<UI_MESSAGE>;
|
|
806
820
|
|
|
@@ -890,12 +904,18 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
890
904
|
if (isAbort) {
|
|
891
905
|
if (isCurrentRequest()) {
|
|
892
906
|
this.setStatus({ status: 'ready' });
|
|
907
|
+
if (this.resumableStreamState === response.state) {
|
|
908
|
+
this.resumableStreamState = undefined;
|
|
909
|
+
}
|
|
893
910
|
}
|
|
894
911
|
return null;
|
|
895
912
|
}
|
|
896
913
|
|
|
897
914
|
if (isCurrentRequest()) {
|
|
898
915
|
this.setStatus({ status: 'ready' });
|
|
916
|
+
if (this.resumableStreamState === response.state) {
|
|
917
|
+
this.resumableStreamState = undefined;
|
|
918
|
+
}
|
|
899
919
|
}
|
|
900
920
|
} catch (err) {
|
|
901
921
|
// Ignore abort errors as they are expected.
|
|
@@ -903,6 +923,9 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
903
923
|
isAbort = true;
|
|
904
924
|
if (isCurrentRequest()) {
|
|
905
925
|
this.setStatus({ status: 'ready' });
|
|
926
|
+
if (this.resumableStreamState === activeResponse?.state) {
|
|
927
|
+
this.resumableStreamState = undefined;
|
|
928
|
+
}
|
|
906
929
|
}
|
|
907
930
|
return null;
|
|
908
931
|
}
|
|
@@ -922,6 +945,12 @@ export abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
922
945
|
isDisconnect = true;
|
|
923
946
|
}
|
|
924
947
|
|
|
948
|
+
if (isDisconnect) {
|
|
949
|
+
this.resumableStreamState = activeResponse?.state;
|
|
950
|
+
} else if (this.resumableStreamState === activeResponse?.state) {
|
|
951
|
+
this.resumableStreamState = undefined;
|
|
952
|
+
}
|
|
953
|
+
|
|
925
954
|
if (this.onError && err instanceof Error) {
|
|
926
955
|
this.onError(err);
|
|
927
956
|
}
|
|
@@ -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.
|
|
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
|
|