ai 6.0.303 → 6.0.305
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 +23 -0
- package/dist/index.d.mts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +73 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -60
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -33
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +1 -33
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-ai-sdk-core/15-tools-and-tool-calling.mdx +14 -1
- package/docs/04-ai-sdk-ui/03-chatbot-resume-streams.mdx +23 -1
- package/docs/04-ai-sdk-ui/03-chatbot-tool-usage.mdx +8 -0
- package/docs/07-reference/02-ai-sdk-ui/01-use-chat.mdx +8 -1
- package/package.json +4 -4
- package/src/prompt/convert-to-language-model-prompt.ts +0 -42
- package/src/ui/chat-transport.ts +7 -0
- package/src/ui/chat.ts +66 -13
- package/src/ui/default-chat-transport.ts +14 -1
- package/src/ui/process-ui-message-stream.ts +23 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# ai
|
|
2
2
|
|
|
3
|
+
## 6.0.305
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [604b4d3]
|
|
8
|
+
- Updated dependencies [0a2b345]
|
|
9
|
+
- Updated dependencies [92ef6a5]
|
|
10
|
+
- @ai-sdk/provider-utils@4.0.58
|
|
11
|
+
- @ai-sdk/gateway@3.0.213
|
|
12
|
+
|
|
13
|
+
## 6.0.304
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- fade070: fix: resume interrupted chat streams when the page becomes visible again
|
|
18
|
+
|
|
19
|
+
`useChat` with `resume: true` no longer starts a second resume request on mount when the chat is already submitted or streaming, e.g. when remounting with a shared `Chat` instance mid-stream.
|
|
20
|
+
|
|
21
|
+
- 8e74de0: fix(ai): update tool outputs in the message containing the matching tool call
|
|
22
|
+
- a5c9cca: fix(ai): prevent duplicate message parts when resuming replayed streams
|
|
23
|
+
- 7888841: fix(ai): update streaming chat messages by stable ID
|
|
24
|
+
- e466fb0: fix(ai): reject approved tool calls without results before sending later context to providers
|
|
25
|
+
|
|
3
26
|
## 6.0.303
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -3677,6 +3677,12 @@ declare function callCompletionApi({ api, prompt, credentials, headers, body, st
|
|
|
3677
3677
|
* @template UI_MESSAGE - The UI message type extending UIMessage
|
|
3678
3678
|
*/
|
|
3679
3679
|
interface ChatTransport<UI_MESSAGE extends UIMessage> {
|
|
3680
|
+
/**
|
|
3681
|
+
* Whether reconnecting returns the complete response from its beginning.
|
|
3682
|
+
* Complete replays must reset the streaming message state before processing
|
|
3683
|
+
* the first start chunk.
|
|
3684
|
+
*/
|
|
3685
|
+
readonly resumeStreamIsReplay?: boolean;
|
|
3680
3686
|
/**
|
|
3681
3687
|
* Sends messages to the chat API endpoint and returns a streaming response.
|
|
3682
3688
|
*
|
|
@@ -4104,7 +4110,15 @@ declare abstract class HttpChatTransport<UI_MESSAGE extends UIMessage> implement
|
|
|
4104
4110
|
}
|
|
4105
4111
|
|
|
4106
4112
|
declare class DefaultChatTransport<UI_MESSAGE extends UIMessage> extends HttpChatTransport<UI_MESSAGE> {
|
|
4107
|
-
|
|
4113
|
+
readonly resumeStreamIsReplay: boolean;
|
|
4114
|
+
constructor({ resumeStreamIsReplay, ...options }?: HttpChatTransportInitOptions<UI_MESSAGE> & {
|
|
4115
|
+
/**
|
|
4116
|
+
* Whether resumed streams replay the response from the beginning.
|
|
4117
|
+
* Defaults to true. Set to false for endpoints that only continue the
|
|
4118
|
+
* interrupted response, even when they emit a start chunk.
|
|
4119
|
+
*/
|
|
4120
|
+
resumeStreamIsReplay?: boolean;
|
|
4121
|
+
});
|
|
4108
4122
|
protected processResponseStream(stream: ReadableStream<Uint8Array<ArrayBufferLike>>): ReadableStream<UIMessageChunk>;
|
|
4109
4123
|
}
|
|
4110
4124
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3677,6 +3677,12 @@ declare function callCompletionApi({ api, prompt, credentials, headers, body, st
|
|
|
3677
3677
|
* @template UI_MESSAGE - The UI message type extending UIMessage
|
|
3678
3678
|
*/
|
|
3679
3679
|
interface ChatTransport<UI_MESSAGE extends UIMessage> {
|
|
3680
|
+
/**
|
|
3681
|
+
* Whether reconnecting returns the complete response from its beginning.
|
|
3682
|
+
* Complete replays must reset the streaming message state before processing
|
|
3683
|
+
* the first start chunk.
|
|
3684
|
+
*/
|
|
3685
|
+
readonly resumeStreamIsReplay?: boolean;
|
|
3680
3686
|
/**
|
|
3681
3687
|
* Sends messages to the chat API endpoint and returns a streaming response.
|
|
3682
3688
|
*
|
|
@@ -4104,7 +4110,15 @@ declare abstract class HttpChatTransport<UI_MESSAGE extends UIMessage> implement
|
|
|
4104
4110
|
}
|
|
4105
4111
|
|
|
4106
4112
|
declare class DefaultChatTransport<UI_MESSAGE extends UIMessage> extends HttpChatTransport<UI_MESSAGE> {
|
|
4107
|
-
|
|
4113
|
+
readonly resumeStreamIsReplay: boolean;
|
|
4114
|
+
constructor({ resumeStreamIsReplay, ...options }?: HttpChatTransportInitOptions<UI_MESSAGE> & {
|
|
4115
|
+
/**
|
|
4116
|
+
* Whether resumed streams replay the response from the beginning.
|
|
4117
|
+
* Defaults to true. Set to false for endpoints that only continue the
|
|
4118
|
+
* interrupted response, even when they emit a start chunk.
|
|
4119
|
+
*/
|
|
4120
|
+
resumeStreamIsReplay?: boolean;
|
|
4121
|
+
});
|
|
4108
4122
|
protected processResponseStream(stream: ReadableStream<Uint8Array<ArrayBufferLike>>): ReadableStream<UIMessageChunk>;
|
|
4109
4123
|
}
|
|
4110
4124
|
|
package/dist/index.js
CHANGED
|
@@ -1335,7 +1335,7 @@ function detectMediaType({
|
|
|
1335
1335
|
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
1336
1336
|
|
|
1337
1337
|
// src/version.ts
|
|
1338
|
-
var VERSION = true ? "6.0.
|
|
1338
|
+
var VERSION = true ? "6.0.305" : "0.0.0-test";
|
|
1339
1339
|
|
|
1340
1340
|
// src/util/download/download.ts
|
|
1341
1341
|
var download = async ({
|
|
@@ -1535,32 +1535,6 @@ async function convertToLanguageModelPrompt({
|
|
|
1535
1535
|
download2 != null ? download2 : createDefaultDownloadFunction(void 0, abortSignal),
|
|
1536
1536
|
supportedUrls
|
|
1537
1537
|
);
|
|
1538
|
-
const approvalIdToToolCallId = /* @__PURE__ */ new Map();
|
|
1539
|
-
for (const message of prompt.messages) {
|
|
1540
|
-
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
1541
|
-
for (const part of message.content) {
|
|
1542
|
-
if (part.type === "tool-approval-request" && "approvalId" in part && "toolCallId" in part) {
|
|
1543
|
-
approvalIdToToolCallId.set(
|
|
1544
|
-
part.approvalId,
|
|
1545
|
-
part.toolCallId
|
|
1546
|
-
);
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
const approvedToolCallIds = /* @__PURE__ */ new Set();
|
|
1552
|
-
for (const message of prompt.messages) {
|
|
1553
|
-
if (message.role === "tool") {
|
|
1554
|
-
for (const part of message.content) {
|
|
1555
|
-
if (part.type === "tool-approval-response") {
|
|
1556
|
-
const toolCallId = approvalIdToToolCallId.get(part.approvalId);
|
|
1557
|
-
if (toolCallId) {
|
|
1558
|
-
approvedToolCallIds.add(toolCallId);
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
1538
|
const messages = [
|
|
1565
1539
|
...prompt.system != null ? typeof prompt.system === "string" ? [{ role: "system", content: prompt.system }] : asArray(prompt.system).map((message) => ({
|
|
1566
1540
|
role: "system",
|
|
@@ -1613,9 +1587,6 @@ async function convertToLanguageModelPrompt({
|
|
|
1613
1587
|
}
|
|
1614
1588
|
case "user":
|
|
1615
1589
|
case "system":
|
|
1616
|
-
for (const id of approvedToolCallIds) {
|
|
1617
|
-
toolCallIds.delete(id);
|
|
1618
|
-
}
|
|
1619
1590
|
if (toolCallIds.size > 0) {
|
|
1620
1591
|
throw new MissingToolResultsError({
|
|
1621
1592
|
toolCallIds: Array.from(toolCallIds)
|
|
@@ -1624,9 +1595,6 @@ async function convertToLanguageModelPrompt({
|
|
|
1624
1595
|
break;
|
|
1625
1596
|
}
|
|
1626
1597
|
}
|
|
1627
|
-
for (const id of approvedToolCallIds) {
|
|
1628
|
-
toolCallIds.delete(id);
|
|
1629
|
-
}
|
|
1630
1598
|
if (toolCallIds.size > 0) {
|
|
1631
1599
|
throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
|
|
1632
1600
|
}
|
|
@@ -6125,13 +6093,15 @@ function processUIMessageStream({
|
|
|
6125
6093
|
onError,
|
|
6126
6094
|
onToolCall,
|
|
6127
6095
|
onData,
|
|
6128
|
-
resetStateOnMessageIdChange = false
|
|
6096
|
+
resetStateOnMessageIdChange = false,
|
|
6097
|
+
resetStateOnFirstMessageStart = false
|
|
6129
6098
|
}) {
|
|
6099
|
+
let isFirstMessageStart = true;
|
|
6130
6100
|
return stream.pipeThrough(
|
|
6131
6101
|
new TransformStream({
|
|
6132
6102
|
async transform(chunk, controller) {
|
|
6133
6103
|
await runUpdateMessageJob(async ({ state, write }) => {
|
|
6134
|
-
var _a23, _b, _c, _d, _e, _f, _g, _h;
|
|
6104
|
+
var _a23, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
6135
6105
|
function getCurrentStepParts() {
|
|
6136
6106
|
const parts = state.message.parts;
|
|
6137
6107
|
let currentStepStartIndex = parts.length - 1;
|
|
@@ -6638,12 +6608,14 @@ function processUIMessageStream({
|
|
|
6638
6608
|
break;
|
|
6639
6609
|
}
|
|
6640
6610
|
case "start": {
|
|
6641
|
-
|
|
6611
|
+
const shouldReset = resetStateOnFirstMessageStart && isFirstMessageStart || resetStateOnMessageIdChange && chunk.messageId != null && chunk.messageId !== state.message.id;
|
|
6612
|
+
isFirstMessageStart = false;
|
|
6613
|
+
if (shouldReset) {
|
|
6642
6614
|
Object.assign(
|
|
6643
6615
|
state,
|
|
6644
6616
|
createStreamingUIMessageState({
|
|
6645
6617
|
lastMessage: void 0,
|
|
6646
|
-
messageId: chunk.messageId
|
|
6618
|
+
messageId: (_i = chunk.messageId) != null ? _i : state.message.id
|
|
6647
6619
|
}),
|
|
6648
6620
|
{ finishReason: void 0 }
|
|
6649
6621
|
);
|
|
@@ -6652,7 +6624,7 @@ function processUIMessageStream({
|
|
|
6652
6624
|
state.message.id = chunk.messageId;
|
|
6653
6625
|
}
|
|
6654
6626
|
await updateMessageMetadata(chunk.messageMetadata);
|
|
6655
|
-
if (chunk.messageId != null || chunk.messageMetadata != null) {
|
|
6627
|
+
if (shouldReset || chunk.messageId != null || chunk.messageMetadata != null) {
|
|
6656
6628
|
write({ updateStatus: false });
|
|
6657
6629
|
}
|
|
6658
6630
|
break;
|
|
@@ -14645,8 +14617,12 @@ var HttpChatTransport = class {
|
|
|
14645
14617
|
|
|
14646
14618
|
// src/ui/default-chat-transport.ts
|
|
14647
14619
|
var DefaultChatTransport = class extends HttpChatTransport {
|
|
14648
|
-
constructor(
|
|
14620
|
+
constructor({
|
|
14621
|
+
resumeStreamIsReplay = true,
|
|
14622
|
+
...options
|
|
14623
|
+
} = {}) {
|
|
14649
14624
|
super(options);
|
|
14625
|
+
this.resumeStreamIsReplay = resumeStreamIsReplay;
|
|
14650
14626
|
}
|
|
14651
14627
|
processResponseStream(stream) {
|
|
14652
14628
|
return (0, import_provider_utils42.parseJsonEventStream)({
|
|
@@ -14791,6 +14767,27 @@ var AbstractChat = class {
|
|
|
14791
14767
|
this.resumeStream = async (options = {}) => {
|
|
14792
14768
|
await this.makeRequest({ trigger: "resume-stream", ...options });
|
|
14793
14769
|
};
|
|
14770
|
+
/**
|
|
14771
|
+
* Resume the stream if the latest response ended with a resumable network
|
|
14772
|
+
* disconnect. If a response is still active, wait for it to settle first so
|
|
14773
|
+
* disconnects reported shortly after the caller's trigger are handled.
|
|
14774
|
+
*
|
|
14775
|
+
* @internal
|
|
14776
|
+
*/
|
|
14777
|
+
this["~resumeStreamIfDisconnected"] = async ({
|
|
14778
|
+
shouldResume = () => true
|
|
14779
|
+
} = {}) => {
|
|
14780
|
+
const activeResponse = this.activeResponse;
|
|
14781
|
+
if (this.resumableStreamState == null && activeResponse != null) {
|
|
14782
|
+
await activeResponse.completionPromise;
|
|
14783
|
+
if (this.resumableStreamState !== activeResponse.state) {
|
|
14784
|
+
return;
|
|
14785
|
+
}
|
|
14786
|
+
}
|
|
14787
|
+
if (this.resumableStreamState != null && shouldResume()) {
|
|
14788
|
+
await this.resumeStream();
|
|
14789
|
+
}
|
|
14790
|
+
};
|
|
14794
14791
|
/**
|
|
14795
14792
|
* Clear the error state and set the status to ready if the chat is in an error state.
|
|
14796
14793
|
*/
|
|
@@ -14851,27 +14848,31 @@ var AbstractChat = class {
|
|
|
14851
14848
|
options
|
|
14852
14849
|
}) => this.jobExecutor.run(async () => {
|
|
14853
14850
|
const messages = this.state.messages;
|
|
14854
|
-
const lastMessage = messages[messages.length - 1];
|
|
14855
14851
|
const updatePart = (part) => isToolUIPart(part) && part.toolCallId === toolCallId ? { ...part, state, output, errorText } : part;
|
|
14856
|
-
|
|
14857
|
-
|
|
14858
|
-
|
|
14859
|
-
|
|
14852
|
+
const messageIndex = messages.findIndex(
|
|
14853
|
+
(message) => message.parts.some(
|
|
14854
|
+
(part) => isToolUIPart(part) && part.toolCallId === toolCallId
|
|
14855
|
+
)
|
|
14856
|
+
);
|
|
14857
|
+
if (messageIndex !== -1) {
|
|
14858
|
+
const message = messages[messageIndex];
|
|
14859
|
+
this.state.replaceMessage(messageIndex, {
|
|
14860
|
+
...message,
|
|
14861
|
+
parts: message.parts.map(updatePart)
|
|
14862
|
+
});
|
|
14863
|
+
}
|
|
14860
14864
|
if (this.activeResponse) {
|
|
14861
14865
|
this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(updatePart);
|
|
14862
14866
|
}
|
|
14863
|
-
if (this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
|
|
14867
|
+
if (messageIndex !== -1 && this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
|
|
14864
14868
|
const shouldSend = await this.shouldSendAutomatically();
|
|
14865
14869
|
if (shouldSend) {
|
|
14866
14870
|
void this.runAutomaticRequest(
|
|
14867
|
-
() => {
|
|
14868
|
-
|
|
14869
|
-
|
|
14870
|
-
|
|
14871
|
-
|
|
14872
|
-
...options
|
|
14873
|
-
});
|
|
14874
|
-
},
|
|
14871
|
+
() => this.makeRequest({
|
|
14872
|
+
trigger: "submit-message",
|
|
14873
|
+
messageId: messages[messageIndex].id,
|
|
14874
|
+
...options
|
|
14875
|
+
}),
|
|
14875
14876
|
shouldSend
|
|
14876
14877
|
);
|
|
14877
14878
|
}
|
|
@@ -15075,6 +15076,7 @@ var AbstractChat = class {
|
|
|
15075
15076
|
const lastMessage = this.lastMessage;
|
|
15076
15077
|
const responseMessageIndex = trigger === "submit-message" && messageId != null ? this.state.messages.findIndex((message) => message.id === messageId) : this.state.messages.length - 1;
|
|
15077
15078
|
const responseMessage = responseMessageIndex === -1 ? lastMessage : this.state.messages[responseMessageIndex];
|
|
15079
|
+
const originalResponseMessageId = responseMessage == null ? void 0 : responseMessage.id;
|
|
15078
15080
|
const resumableResponseMessage = trigger === "resume-stream" && (responseMessage == null ? void 0 : responseMessage.role) === "assistant" && responseMessage.parts.some(
|
|
15079
15081
|
(part) => isToolUIPart(part) && part.state === "input-streaming"
|
|
15080
15082
|
) ? this.state.snapshot(responseMessage) : void 0;
|
|
@@ -15121,23 +15123,32 @@ var AbstractChat = class {
|
|
|
15121
15123
|
return job({
|
|
15122
15124
|
state: response.state,
|
|
15123
15125
|
write: ({ updateStatus = true } = {}) => {
|
|
15124
|
-
var _a24;
|
|
15125
15126
|
if (response.abortController.signal.aborted) {
|
|
15126
15127
|
return;
|
|
15127
15128
|
}
|
|
15128
15129
|
if (updateStatus) {
|
|
15129
15130
|
this.setStatus({ status: "streaming" });
|
|
15130
15131
|
}
|
|
15131
|
-
|
|
15132
|
+
const existingMessageIndex = this.state.messages.findLastIndex(
|
|
15133
|
+
(message) => message.id === response.state.message.id
|
|
15134
|
+
);
|
|
15135
|
+
if (existingMessageIndex !== -1) {
|
|
15132
15136
|
this.state.replaceMessage(
|
|
15133
|
-
|
|
15137
|
+
existingMessageIndex,
|
|
15134
15138
|
response.state.message
|
|
15135
15139
|
);
|
|
15136
|
-
} else if (
|
|
15137
|
-
this.state.
|
|
15138
|
-
|
|
15139
|
-
response.state.message
|
|
15140
|
+
} else if (usesEarlierAssistantMessage) {
|
|
15141
|
+
const originalMessageIndex = this.state.messages.findLastIndex(
|
|
15142
|
+
(message) => message.id === originalResponseMessageId
|
|
15140
15143
|
);
|
|
15144
|
+
if (originalMessageIndex !== -1) {
|
|
15145
|
+
this.state.replaceMessage(
|
|
15146
|
+
originalMessageIndex,
|
|
15147
|
+
response.state.message
|
|
15148
|
+
);
|
|
15149
|
+
} else {
|
|
15150
|
+
this.state.pushMessage(response.state.message);
|
|
15151
|
+
}
|
|
15141
15152
|
} else {
|
|
15142
15153
|
this.state.pushMessage(response.state.message);
|
|
15143
15154
|
}
|
|
@@ -15148,6 +15159,8 @@ var AbstractChat = class {
|
|
|
15148
15159
|
await consumeStream({
|
|
15149
15160
|
stream: processUIMessageStream({
|
|
15150
15161
|
stream,
|
|
15162
|
+
resetStateOnMessageIdChange: trigger === "resume-stream",
|
|
15163
|
+
resetStateOnFirstMessageStart: trigger === "resume-stream" && this.transport.resumeStreamIsReplay,
|
|
15151
15164
|
onToolCall: this.onToolCall,
|
|
15152
15165
|
onData: this.onData,
|
|
15153
15166
|
messageMetadataSchema: this.messageMetadataSchema,
|