ai 6.0.311 → 6.0.313
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 +24 -0
- package/dist/index.js +52 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +52 -11
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index.mjs +1 -1
- package/docs/03-ai-sdk-core/16-mcp-tools.mdx +29 -2
- package/docs/03-ai-sdk-core/37-speech.mdx +1 -0
- package/package.json +4 -4
- package/src/generate-text/collect-tool-approvals.ts +10 -0
- package/src/generate-text/prune-messages.ts +85 -32
- package/src/ui/process-ui-message-stream.ts +1 -0
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.313" : "0.0.0-test";
|
|
168
168
|
|
|
169
169
|
// src/util/download/download.ts
|
|
170
170
|
var download = async ({
|
package/dist/internal/index.mjs
CHANGED
|
@@ -156,6 +156,33 @@ tokens are invalid.
|
|
|
156
156
|
|
|
157
157
|
### OAuth Authorization Server Validation
|
|
158
158
|
|
|
159
|
+
Pre-registered confidential clients must be bound to their authorization server
|
|
160
|
+
before starting OAuth. Set `issuer` on the credentials returned by
|
|
161
|
+
`clientInformation()` to the issuer of the server that registered the client:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
clientInformation() {
|
|
165
|
+
return {
|
|
166
|
+
client_id: process.env.OAUTH_CLIENT_ID!,
|
|
167
|
+
client_secret: process.env.OAUTH_CLIENT_SECRET!,
|
|
168
|
+
issuer: 'https://accounts.example.com',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The issuer must exactly match the discovered issuer. The SDK rejects a mismatch
|
|
174
|
+
before redirecting or sending credentials, even if a stored authorization flow
|
|
175
|
+
pin names the discovered server. Dynamic client registration attaches this
|
|
176
|
+
binding automatically.
|
|
177
|
+
|
|
178
|
+
Existing complete authorization server bindings on credentials, stored tokens,
|
|
179
|
+
or `authorizationServerInformation()` are also supported. Without a binding,
|
|
180
|
+
a pre-registered client secret or custom `addClientAuthentication` handler is
|
|
181
|
+
rejected, even when `validateAuthorizationServerURL` accepts the selected server.
|
|
182
|
+
Approving a server does not establish that the credentials belong to it.
|
|
183
|
+
Do not derive the credential issuer from the MCP server's metadata; configure it
|
|
184
|
+
from the client's registration.
|
|
185
|
+
|
|
159
186
|
When using MCP OAuth in server-side applications, the MCP server can advertise
|
|
160
187
|
the OAuth authorization server to use. If you connect to MCP servers outside
|
|
161
188
|
your control, implement `validateAuthorizationServerURL` on your
|
|
@@ -183,8 +210,8 @@ const myOAuthClientProvider = {
|
|
|
183
210
|
```
|
|
184
211
|
|
|
185
212
|
This hook is called before the SDK fetches authorization server metadata, so a
|
|
186
|
-
rejected URL is not requested.
|
|
187
|
-
|
|
213
|
+
rejected URL is not requested. The hook is an optional additional restriction;
|
|
214
|
+
it does not replace the credential binding required for confidential clients.
|
|
188
215
|
|
|
189
216
|
### OAuth Callback Issuer Validation
|
|
190
217
|
|
|
@@ -142,6 +142,7 @@ try {
|
|
|
142
142
|
| [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `tts-1-hd` |
|
|
143
143
|
| [OpenAI](/providers/ai-sdk-providers/openai#speech-models) | `gpt-4o-mini-tts` |
|
|
144
144
|
| [Mistral](/providers/ai-sdk-providers/mistral#speech-models) | `voxtral-mini-tts-2603` |
|
|
145
|
+
| [Mistral](/providers/ai-sdk-providers/mistral#speech-models) | `voxtral-mini-tts-3-0` |
|
|
145
146
|
| [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2.1-flash` |
|
|
146
147
|
| [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2.1` |
|
|
147
148
|
| [Azure Speech](/providers/ai-sdk-providers/azure#mai-voice) | `mai-voice-2-flash` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.313",
|
|
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.220",
|
|
49
49
|
"@ai-sdk/provider": "3.0.19",
|
|
50
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
50
|
+
"@ai-sdk/provider-utils": "4.0.62"
|
|
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.137",
|
|
62
62
|
"@ai-sdk/test-server": "1.0.6",
|
|
63
63
|
"@vercel/ai-tsconfig": "0.0.0"
|
|
64
64
|
},
|
|
@@ -73,6 +73,7 @@ export function collectToolApprovals<TOOLS extends ToolSet>({
|
|
|
73
73
|
|
|
74
74
|
const approvedToolApprovals: Array<CollectedToolApprovals<TOOLS>> = [];
|
|
75
75
|
const deniedToolApprovals: Array<CollectedToolApprovals<TOOLS>> = [];
|
|
76
|
+
const collectedToolCallIds = new Set<string>();
|
|
76
77
|
|
|
77
78
|
const approvalResponses = lastMessage.content.filter(
|
|
78
79
|
part => part.type === 'tool-approval-response',
|
|
@@ -99,6 +100,15 @@ export function collectToolApprovals<TOOLS extends ToolSet>({
|
|
|
99
100
|
});
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
// Only the first response for a tool call is collected. Later responses
|
|
104
|
+
// (replays, conflicting decisions, or responses to another approval of the
|
|
105
|
+
// same call) would otherwise execute the tool twice or both execute and
|
|
106
|
+
// deny it.
|
|
107
|
+
if (collectedToolCallIds.has(toolCall.toolCallId)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
collectedToolCallIds.add(toolCall.toolCallId);
|
|
111
|
+
|
|
102
112
|
const approval: CollectedToolApprovals<TOOLS> = {
|
|
103
113
|
approvalRequest,
|
|
104
114
|
approvalResponse,
|
|
@@ -161,42 +161,95 @@ export function pruneMessages({
|
|
|
161
161
|
return message;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
164
|
+
const keepParts = message.content.map(part => {
|
|
165
|
+
// keep non-tool parts:
|
|
166
|
+
if (
|
|
167
|
+
part.type !== 'tool-call' &&
|
|
168
|
+
part.type !== 'tool-result' &&
|
|
169
|
+
part.type !== 'tool-approval-request' &&
|
|
170
|
+
part.type !== 'tool-approval-response'
|
|
171
|
+
) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// keep parts that are associated with a tool call or approval that needs to be kept:
|
|
176
|
+
if (
|
|
177
|
+
((part.type === 'tool-call' || part.type === 'tool-result') &&
|
|
178
|
+
keptToolCallIds.has(part.toolCallId)) ||
|
|
179
|
+
((part.type === 'tool-approval-request' ||
|
|
180
|
+
part.type === 'tool-approval-response') &&
|
|
181
|
+
keptApprovalIds.has(part.approvalId))
|
|
182
|
+
) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// keep parts that are not associated with a tool that should be removed:
|
|
187
|
+
const partToolName =
|
|
188
|
+
part.type === 'tool-call' || part.type === 'tool-result'
|
|
189
|
+
? part.toolName
|
|
190
|
+
: approvalIdToToolName.get(part.approvalId);
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
toolCall.tools != null &&
|
|
194
|
+
partToolName != null &&
|
|
195
|
+
!toolCall.tools.includes(partToolName)
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Consecutive reasoning parts can belong to the same provider item.
|
|
200
|
+
// Remove the whole group when its following content was pruned.
|
|
201
|
+
if (message.role === 'assistant') {
|
|
202
|
+
for (
|
|
203
|
+
let reasoningIndex = 0;
|
|
204
|
+
reasoningIndex < message.content.length;
|
|
205
|
+
reasoningIndex++
|
|
206
|
+
) {
|
|
207
|
+
const part = message.content[reasoningIndex];
|
|
208
|
+
if (part.type !== 'reasoning') {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
let reasoningEndIndex = reasoningIndex + 1;
|
|
213
|
+
while (reasoningEndIndex < message.content.length) {
|
|
214
|
+
const nextPart = message.content[reasoningEndIndex];
|
|
215
|
+
if (nextPart.type !== 'reasoning') {
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
reasoningEndIndex++;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let followingPartIndex = reasoningEndIndex;
|
|
222
|
+
let hasFollowingPart = false;
|
|
223
|
+
let hasKeptFollowingPart = false;
|
|
224
|
+
|
|
225
|
+
while (followingPartIndex < message.content.length) {
|
|
226
|
+
const followingPart = message.content[followingPartIndex];
|
|
227
|
+
if (followingPart.type === 'reasoning') {
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
hasFollowingPart = true;
|
|
232
|
+
hasKeptFollowingPart ||= keepParts[followingPartIndex];
|
|
233
|
+
followingPartIndex++;
|
|
175
234
|
}
|
|
176
235
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return true;
|
|
236
|
+
if (hasFollowingPart && !hasKeptFollowingPart) {
|
|
237
|
+
for (
|
|
238
|
+
let index = reasoningIndex;
|
|
239
|
+
index < reasoningEndIndex;
|
|
240
|
+
index++
|
|
241
|
+
) {
|
|
242
|
+
keepParts[index] = false;
|
|
243
|
+
}
|
|
186
244
|
}
|
|
187
245
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
toolCall.tools != null &&
|
|
196
|
-
partToolName != null &&
|
|
197
|
-
!toolCall.tools.includes(partToolName)
|
|
198
|
-
);
|
|
199
|
-
}),
|
|
246
|
+
reasoningIndex = followingPartIndex - 1;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
...message,
|
|
252
|
+
content: message.content.filter((_, index) => keepParts[index]),
|
|
200
253
|
} as AssistantModelMessage | ToolModelMessage;
|
|
201
254
|
});
|
|
202
255
|
}
|
|
@@ -253,6 +253,7 @@ export function processUIMessageStream<UI_MESSAGE extends UIMessage>({
|
|
|
253
253
|
|
|
254
254
|
if (part != null) {
|
|
255
255
|
part.state = options.state;
|
|
256
|
+
anyPart.type = `tool-${options.toolName}`;
|
|
256
257
|
anyPart.input = anyOptions.input;
|
|
257
258
|
anyPart.output = anyOptions.output;
|
|
258
259
|
anyPart.errorText = anyOptions.errorText;
|