ai 6.0.248 → 6.0.250
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 +20 -0
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +94 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +94 -22
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.mjs +1 -1
- package/package.json +3 -3
- package/src/generate-object/stream-object.ts +2 -0
- package/src/generate-text/stream-text.ts +1 -0
- package/src/telemetry/record-span.ts +5 -2
- package/src/test/mock-tracer.ts +2 -0
- package/src/ui/chat-transport.ts +3 -0
- package/src/ui/chat.ts +88 -13
- package/src/ui/http-chat-transport.ts +1 -0
- package/src/util/consume-stream.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# ai
|
|
2
2
|
|
|
3
|
+
## 6.0.250
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a077695: Prevent streaming telemetry spans from ending twice when model calls fail.
|
|
8
|
+
- 7ce3b8c: Prevent `resumeStream` from copying the previous assistant message into the resumed response.
|
|
9
|
+
- Updated dependencies [b2a4d5a]
|
|
10
|
+
- @ai-sdk/provider-utils@4.0.45
|
|
11
|
+
- @ai-sdk/gateway@3.0.170
|
|
12
|
+
|
|
13
|
+
## 6.0.249
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- a774b7b: Stop pending and active resumed chat streams after cancellation, and prevent
|
|
18
|
+
overlapping resumptions from applying stale updates.
|
|
19
|
+
- Updated dependencies [b39f987]
|
|
20
|
+
- Updated dependencies [d79117b]
|
|
21
|
+
- @ai-sdk/gateway@3.0.169
|
|
22
|
+
|
|
3
23
|
## 6.0.248
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -3620,6 +3620,7 @@ interface ChatTransport<UI_MESSAGE extends UIMessage> {
|
|
|
3620
3620
|
*
|
|
3621
3621
|
* @param options - Configuration object containing:
|
|
3622
3622
|
* @param options.chatId - Unique identifier for the chat session to reconnect to
|
|
3623
|
+
* @param options.abortSignal - Signal to abort the reconnection request if needed
|
|
3623
3624
|
* @param options.headers - Additional HTTP headers to include in the reconnection request
|
|
3624
3625
|
* @param options.body - Additional JSON properties to include in the request body
|
|
3625
3626
|
* @param options.metadata - Custom metadata to attach to the request
|
|
@@ -3633,6 +3634,8 @@ interface ChatTransport<UI_MESSAGE extends UIMessage> {
|
|
|
3633
3634
|
reconnectToStream: (options: {
|
|
3634
3635
|
/** Unique identifier for the chat session to reconnect to */
|
|
3635
3636
|
chatId: string;
|
|
3637
|
+
/** Signal to abort the reconnection request if needed */
|
|
3638
|
+
abortSignal?: AbortSignal;
|
|
3636
3639
|
} & ChatRequestOptions) => Promise<ReadableStream<UIMessageChunk> | null>;
|
|
3637
3640
|
}
|
|
3638
3641
|
|
|
@@ -3793,6 +3796,7 @@ declare abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
3793
3796
|
private onData?;
|
|
3794
3797
|
private sendAutomaticallyWhen?;
|
|
3795
3798
|
private activeResponse;
|
|
3799
|
+
private activeResumeRequest;
|
|
3796
3800
|
private jobExecutor;
|
|
3797
3801
|
constructor({ generateId, id, transport, messageMetadataSchema, dataPartSchemas, state, onError, onToolCall, onFinish, onData, sendAutomaticallyWhen, }: Omit<ChatInit<UI_MESSAGE>, 'messages'> & {
|
|
3798
3802
|
state: ChatState<UI_MESSAGE>;
|
|
@@ -5264,9 +5268,10 @@ declare function generateObject<SCHEMA extends FlexibleSchema<unknown> = Flexibl
|
|
|
5264
5268
|
* @param options.onError - Optional callback to handle errors that occur during consumption.
|
|
5265
5269
|
* @returns A promise that resolves when the stream is fully consumed.
|
|
5266
5270
|
*/
|
|
5267
|
-
declare function consumeStream({ stream, onError, }: {
|
|
5271
|
+
declare function consumeStream({ stream, onError, abortSignal, }: {
|
|
5268
5272
|
stream: ReadableStream;
|
|
5269
5273
|
onError?: (error: unknown) => void;
|
|
5274
|
+
abortSignal?: AbortSignal;
|
|
5270
5275
|
}): Promise<void>;
|
|
5271
5276
|
|
|
5272
5277
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -3620,6 +3620,7 @@ interface ChatTransport<UI_MESSAGE extends UIMessage> {
|
|
|
3620
3620
|
*
|
|
3621
3621
|
* @param options - Configuration object containing:
|
|
3622
3622
|
* @param options.chatId - Unique identifier for the chat session to reconnect to
|
|
3623
|
+
* @param options.abortSignal - Signal to abort the reconnection request if needed
|
|
3623
3624
|
* @param options.headers - Additional HTTP headers to include in the reconnection request
|
|
3624
3625
|
* @param options.body - Additional JSON properties to include in the request body
|
|
3625
3626
|
* @param options.metadata - Custom metadata to attach to the request
|
|
@@ -3633,6 +3634,8 @@ interface ChatTransport<UI_MESSAGE extends UIMessage> {
|
|
|
3633
3634
|
reconnectToStream: (options: {
|
|
3634
3635
|
/** Unique identifier for the chat session to reconnect to */
|
|
3635
3636
|
chatId: string;
|
|
3637
|
+
/** Signal to abort the reconnection request if needed */
|
|
3638
|
+
abortSignal?: AbortSignal;
|
|
3636
3639
|
} & ChatRequestOptions) => Promise<ReadableStream<UIMessageChunk> | null>;
|
|
3637
3640
|
}
|
|
3638
3641
|
|
|
@@ -3793,6 +3796,7 @@ declare abstract class AbstractChat<UI_MESSAGE extends UIMessage> {
|
|
|
3793
3796
|
private onData?;
|
|
3794
3797
|
private sendAutomaticallyWhen?;
|
|
3795
3798
|
private activeResponse;
|
|
3799
|
+
private activeResumeRequest;
|
|
3796
3800
|
private jobExecutor;
|
|
3797
3801
|
constructor({ generateId, id, transport, messageMetadataSchema, dataPartSchemas, state, onError, onToolCall, onFinish, onData, sendAutomaticallyWhen, }: Omit<ChatInit<UI_MESSAGE>, 'messages'> & {
|
|
3798
3802
|
state: ChatState<UI_MESSAGE>;
|
|
@@ -5264,9 +5268,10 @@ declare function generateObject<SCHEMA extends FlexibleSchema<unknown> = Flexibl
|
|
|
5264
5268
|
* @param options.onError - Optional callback to handle errors that occur during consumption.
|
|
5265
5269
|
* @returns A promise that resolves when the stream is fully consumed.
|
|
5266
5270
|
*/
|
|
5267
|
-
declare function consumeStream({ stream, onError, }: {
|
|
5271
|
+
declare function consumeStream({ stream, onError, abortSignal, }: {
|
|
5268
5272
|
stream: ReadableStream;
|
|
5269
5273
|
onError?: (error: unknown) => void;
|
|
5274
|
+
abortSignal?: AbortSignal;
|
|
5270
5275
|
}): Promise<void>;
|
|
5271
5276
|
|
|
5272
5277
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1304,7 +1304,7 @@ function detectMediaType({
|
|
|
1304
1304
|
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
1305
1305
|
|
|
1306
1306
|
// src/version.ts
|
|
1307
|
-
var VERSION = true ? "6.0.
|
|
1307
|
+
var VERSION = true ? "6.0.250" : "0.0.0-test";
|
|
1308
1308
|
|
|
1309
1309
|
// src/util/download/download.ts
|
|
1310
1310
|
var download = async ({
|
|
@@ -2532,7 +2532,8 @@ async function recordSpan({
|
|
|
2532
2532
|
tracer,
|
|
2533
2533
|
attributes,
|
|
2534
2534
|
fn,
|
|
2535
|
-
endWhenDone = true
|
|
2535
|
+
endWhenDone = true,
|
|
2536
|
+
endOnError = endWhenDone
|
|
2536
2537
|
}) {
|
|
2537
2538
|
return tracer.startActiveSpan(
|
|
2538
2539
|
name22,
|
|
@@ -2549,7 +2550,9 @@ async function recordSpan({
|
|
|
2549
2550
|
try {
|
|
2550
2551
|
recordErrorOnSpan(span, error);
|
|
2551
2552
|
} finally {
|
|
2552
|
-
|
|
2553
|
+
if (endOnError) {
|
|
2554
|
+
span.end();
|
|
2555
|
+
}
|
|
2553
2556
|
}
|
|
2554
2557
|
throw error;
|
|
2555
2558
|
}
|
|
@@ -6591,9 +6594,19 @@ function createAsyncIterableStream(source) {
|
|
|
6591
6594
|
// src/util/consume-stream.ts
|
|
6592
6595
|
async function consumeStream({
|
|
6593
6596
|
stream,
|
|
6594
|
-
onError
|
|
6597
|
+
onError,
|
|
6598
|
+
abortSignal
|
|
6595
6599
|
}) {
|
|
6596
6600
|
const reader = stream.getReader();
|
|
6601
|
+
const cancelOnAbort = () => {
|
|
6602
|
+
reader.cancel().catch(() => {
|
|
6603
|
+
});
|
|
6604
|
+
};
|
|
6605
|
+
if (abortSignal == null ? void 0 : abortSignal.aborted) {
|
|
6606
|
+
cancelOnAbort();
|
|
6607
|
+
} else {
|
|
6608
|
+
abortSignal == null ? void 0 : abortSignal.addEventListener("abort", cancelOnAbort, { once: true });
|
|
6609
|
+
}
|
|
6597
6610
|
try {
|
|
6598
6611
|
while (true) {
|
|
6599
6612
|
const { done } = await reader.read();
|
|
@@ -6603,6 +6616,7 @@ async function consumeStream({
|
|
|
6603
6616
|
} catch (error) {
|
|
6604
6617
|
onError == null ? void 0 : onError(error);
|
|
6605
6618
|
} finally {
|
|
6619
|
+
abortSignal == null ? void 0 : abortSignal.removeEventListener("abort", cancelOnAbort);
|
|
6606
6620
|
reader.releaseLock();
|
|
6607
6621
|
}
|
|
6608
6622
|
}
|
|
@@ -7890,6 +7904,7 @@ var DefaultStreamTextResult = class {
|
|
|
7890
7904
|
}),
|
|
7891
7905
|
tracer,
|
|
7892
7906
|
endWhenDone: false,
|
|
7907
|
+
endOnError: true,
|
|
7893
7908
|
fn: async (doStreamSpan2) => ({
|
|
7894
7909
|
startTimestampMs: now2(),
|
|
7895
7910
|
// get before the call
|
|
@@ -11388,6 +11403,7 @@ var DefaultStreamObjectResult = class {
|
|
|
11388
11403
|
}),
|
|
11389
11404
|
tracer,
|
|
11390
11405
|
endWhenDone: false,
|
|
11406
|
+
endOnError: true,
|
|
11391
11407
|
fn: async (rootSpan) => {
|
|
11392
11408
|
const standardizedPrompt = await standardizePrompt({
|
|
11393
11409
|
system,
|
|
@@ -11459,6 +11475,7 @@ var DefaultStreamObjectResult = class {
|
|
|
11459
11475
|
}),
|
|
11460
11476
|
tracer,
|
|
11461
11477
|
endWhenDone: false,
|
|
11478
|
+
endOnError: true,
|
|
11462
11479
|
fn: async (doStreamSpan2) => ({
|
|
11463
11480
|
startTimestampMs: now2(),
|
|
11464
11481
|
doStreamSpan: doStreamSpan2,
|
|
@@ -13672,7 +13689,8 @@ var HttpChatTransport = class {
|
|
|
13672
13689
|
const response = await fetch2(api, {
|
|
13673
13690
|
method: "GET",
|
|
13674
13691
|
headers,
|
|
13675
|
-
credentials
|
|
13692
|
+
credentials,
|
|
13693
|
+
signal: options.abortSignal
|
|
13676
13694
|
});
|
|
13677
13695
|
if (response.status === 204) {
|
|
13678
13696
|
return null;
|
|
@@ -13727,6 +13745,7 @@ var AbstractChat = class {
|
|
|
13727
13745
|
sendAutomaticallyWhen
|
|
13728
13746
|
}) {
|
|
13729
13747
|
this.activeResponse = void 0;
|
|
13748
|
+
this.activeResumeRequest = void 0;
|
|
13730
13749
|
this.jobExecutor = new SerialJobExecutor();
|
|
13731
13750
|
/**
|
|
13732
13751
|
* Appends or replaces a user message to the chat list. This triggers the API call to fetch
|
|
@@ -13896,12 +13915,9 @@ var AbstractChat = class {
|
|
|
13896
13915
|
* Abort the current request immediately, keep the generated tokens if any.
|
|
13897
13916
|
*/
|
|
13898
13917
|
this.stop = async () => {
|
|
13899
|
-
var _a22;
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
if ((_a22 = this.activeResponse) == null ? void 0 : _a22.abortController) {
|
|
13903
|
-
this.activeResponse.abortController.abort();
|
|
13904
|
-
}
|
|
13918
|
+
var _a22, _b;
|
|
13919
|
+
(_a22 = this.activeResumeRequest) == null ? void 0 : _a22.abortController.abort();
|
|
13920
|
+
(_b = this.activeResponse) == null ? void 0 : _b.abortController.abort();
|
|
13905
13921
|
};
|
|
13906
13922
|
this.id = id;
|
|
13907
13923
|
this.transport = transport;
|
|
@@ -13965,25 +13981,60 @@ var AbstractChat = class {
|
|
|
13965
13981
|
body,
|
|
13966
13982
|
messageId
|
|
13967
13983
|
}) {
|
|
13968
|
-
var _a22, _b;
|
|
13984
|
+
var _a22, _b, _c;
|
|
13985
|
+
const abortController = new AbortController();
|
|
13986
|
+
const activeResumeRequest = trigger === "resume-stream" ? { abortController } : void 0;
|
|
13987
|
+
if (activeResumeRequest) {
|
|
13988
|
+
(_a22 = this.activeResumeRequest) == null ? void 0 : _a22.abortController.abort();
|
|
13989
|
+
this.activeResumeRequest = activeResumeRequest;
|
|
13990
|
+
}
|
|
13991
|
+
const isCurrentRequest = () => activeResumeRequest == null || this.activeResumeRequest === activeResumeRequest;
|
|
13992
|
+
const clearActiveResumeRequest = () => {
|
|
13993
|
+
if (this.activeResumeRequest === activeResumeRequest) {
|
|
13994
|
+
this.activeResumeRequest = void 0;
|
|
13995
|
+
}
|
|
13996
|
+
};
|
|
13969
13997
|
let resumeStream;
|
|
13970
13998
|
if (trigger === "resume-stream") {
|
|
13971
13999
|
try {
|
|
13972
14000
|
const reconnect = await this.transport.reconnectToStream({
|
|
13973
14001
|
chatId: this.id,
|
|
14002
|
+
abortSignal: abortController.signal,
|
|
13974
14003
|
metadata,
|
|
13975
14004
|
headers,
|
|
13976
14005
|
body
|
|
13977
14006
|
});
|
|
14007
|
+
if (abortController.signal.aborted || !isCurrentRequest()) {
|
|
14008
|
+
await (reconnect == null ? void 0 : reconnect.cancel().catch(() => {
|
|
14009
|
+
}));
|
|
14010
|
+
if (isCurrentRequest()) {
|
|
14011
|
+
this.setStatus({ status: "ready" });
|
|
14012
|
+
}
|
|
14013
|
+
clearActiveResumeRequest();
|
|
14014
|
+
return;
|
|
14015
|
+
}
|
|
13978
14016
|
if (reconnect == null) {
|
|
14017
|
+
this.setStatus({ status: "ready" });
|
|
14018
|
+
clearActiveResumeRequest();
|
|
13979
14019
|
return;
|
|
13980
14020
|
}
|
|
13981
14021
|
resumeStream = reconnect;
|
|
13982
14022
|
} catch (err) {
|
|
14023
|
+
if (abortController.signal.aborted || err.name === "AbortError") {
|
|
14024
|
+
if (isCurrentRequest()) {
|
|
14025
|
+
this.setStatus({ status: "ready" });
|
|
14026
|
+
}
|
|
14027
|
+
clearActiveResumeRequest();
|
|
14028
|
+
return;
|
|
14029
|
+
}
|
|
14030
|
+
if (!isCurrentRequest()) {
|
|
14031
|
+
return;
|
|
14032
|
+
}
|
|
13983
14033
|
if (this.onError && err instanceof Error) {
|
|
13984
14034
|
this.onError(err);
|
|
13985
14035
|
}
|
|
13986
14036
|
this.setStatus({ status: "error", error: err });
|
|
14037
|
+
clearActiveResumeRequest();
|
|
13987
14038
|
return;
|
|
13988
14039
|
}
|
|
13989
14040
|
}
|
|
@@ -13996,10 +14047,10 @@ var AbstractChat = class {
|
|
|
13996
14047
|
try {
|
|
13997
14048
|
const response = {
|
|
13998
14049
|
state: createStreamingUIMessageState({
|
|
13999
|
-
lastMessage: trigger === "regenerate-message" ? void 0 : this.state.snapshot(lastMessage),
|
|
14050
|
+
lastMessage: trigger === "resume-stream" || trigger === "regenerate-message" ? void 0 : this.state.snapshot(lastMessage),
|
|
14000
14051
|
messageId: this.generateId()
|
|
14001
14052
|
}),
|
|
14002
|
-
abortController
|
|
14053
|
+
abortController
|
|
14003
14054
|
};
|
|
14004
14055
|
activeResponse = response;
|
|
14005
14056
|
response.abortController.signal.addEventListener("abort", () => {
|
|
@@ -14023,11 +14074,17 @@ var AbstractChat = class {
|
|
|
14023
14074
|
}
|
|
14024
14075
|
const runUpdateMessageJob = (job) => (
|
|
14025
14076
|
// serialize the job execution to avoid race conditions:
|
|
14026
|
-
this.jobExecutor.run(
|
|
14027
|
-
()
|
|
14077
|
+
this.jobExecutor.run(() => {
|
|
14078
|
+
if (response.abortController.signal.aborted) {
|
|
14079
|
+
return Promise.resolve();
|
|
14080
|
+
}
|
|
14081
|
+
return job({
|
|
14028
14082
|
state: response.state,
|
|
14029
14083
|
write: () => {
|
|
14030
14084
|
var _a23;
|
|
14085
|
+
if (response.abortController.signal.aborted) {
|
|
14086
|
+
return;
|
|
14087
|
+
}
|
|
14031
14088
|
this.setStatus({ status: "streaming" });
|
|
14032
14089
|
const replaceLastMessage = response.state.message.id === ((_a23 = this.lastMessage) == null ? void 0 : _a23.id);
|
|
14033
14090
|
if (replaceLastMessage) {
|
|
@@ -14039,8 +14096,8 @@ var AbstractChat = class {
|
|
|
14039
14096
|
this.state.pushMessage(response.state.message);
|
|
14040
14097
|
}
|
|
14041
14098
|
}
|
|
14042
|
-
})
|
|
14043
|
-
)
|
|
14099
|
+
});
|
|
14100
|
+
})
|
|
14044
14101
|
);
|
|
14045
14102
|
await consumeStream({
|
|
14046
14103
|
stream: processUIMessageStream({
|
|
@@ -14054,15 +14111,29 @@ var AbstractChat = class {
|
|
|
14054
14111
|
throw error;
|
|
14055
14112
|
}
|
|
14056
14113
|
}),
|
|
14114
|
+
abortSignal: response.abortController.signal,
|
|
14057
14115
|
onError: (error) => {
|
|
14058
14116
|
throw error;
|
|
14059
14117
|
}
|
|
14060
14118
|
});
|
|
14061
|
-
|
|
14119
|
+
if (isAbort) {
|
|
14120
|
+
if (isCurrentRequest()) {
|
|
14121
|
+
this.setStatus({ status: "ready" });
|
|
14122
|
+
}
|
|
14123
|
+
return null;
|
|
14124
|
+
}
|
|
14125
|
+
if (isCurrentRequest()) {
|
|
14126
|
+
this.setStatus({ status: "ready" });
|
|
14127
|
+
}
|
|
14062
14128
|
} catch (err) {
|
|
14063
14129
|
if (isAbort || err.name === "AbortError") {
|
|
14064
14130
|
isAbort = true;
|
|
14065
|
-
|
|
14131
|
+
if (isCurrentRequest()) {
|
|
14132
|
+
this.setStatus({ status: "ready" });
|
|
14133
|
+
}
|
|
14134
|
+
return null;
|
|
14135
|
+
}
|
|
14136
|
+
if (!isCurrentRequest()) {
|
|
14066
14137
|
return null;
|
|
14067
14138
|
}
|
|
14068
14139
|
isError = true;
|
|
@@ -14076,7 +14147,7 @@ var AbstractChat = class {
|
|
|
14076
14147
|
} finally {
|
|
14077
14148
|
try {
|
|
14078
14149
|
if (activeResponse) {
|
|
14079
|
-
(
|
|
14150
|
+
(_b = this.onFinish) == null ? void 0 : _b.call(this, {
|
|
14080
14151
|
message: activeResponse.state.message,
|
|
14081
14152
|
messages: this.state.messages,
|
|
14082
14153
|
isAbort,
|
|
@@ -14091,11 +14162,12 @@ var AbstractChat = class {
|
|
|
14091
14162
|
if (this.activeResponse === activeResponse) {
|
|
14092
14163
|
this.activeResponse = void 0;
|
|
14093
14164
|
}
|
|
14165
|
+
clearActiveResumeRequest();
|
|
14094
14166
|
}
|
|
14095
14167
|
if (!isError && await this.shouldSendAutomatically()) {
|
|
14096
14168
|
await this.makeRequest({
|
|
14097
14169
|
trigger: "submit-message",
|
|
14098
|
-
messageId: (
|
|
14170
|
+
messageId: (_c = this.lastMessage) == null ? void 0 : _c.id,
|
|
14099
14171
|
metadata,
|
|
14100
14172
|
headers,
|
|
14101
14173
|
body
|