ai 6.0.265 → 6.0.266
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 +10 -0
- package/dist/index.js +86 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -21
- 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 +2 -2
- package/package.json +3 -3
- package/src/generate-text/generate-text.ts +21 -1
- package/src/generate-text/stream-text.ts +69 -13
- package/src/generate-text/validate-tool-approvals.ts +24 -8
- package/src/util/create-stitchable-stream.ts +9 -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.266" : "0.0.0-test";
|
|
168
168
|
|
|
169
169
|
// src/util/download/download.ts
|
|
170
170
|
var download = async ({
|
package/dist/internal/index.mjs
CHANGED
|
@@ -158,8 +158,8 @@ Here are the capabilities of popular models:
|
|
|
158
158
|
| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-medium-3.5` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
159
159
|
| [Mistral](/providers/ai-sdk-providers/mistral) | `mistral-small-latest` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
160
160
|
| [Mistral](/providers/ai-sdk-providers/mistral) | `pixtral-12b-2409` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
161
|
-
| [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-
|
|
162
|
-
| [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-
|
|
161
|
+
| [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-v4-flash` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
162
|
+
| [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-v4-pro` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
163
163
|
| [Cerebras](/providers/ai-sdk-providers/cerebras) | `llama3.1-8b` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
164
164
|
| [Cerebras](/providers/ai-sdk-providers/cerebras) | `llama3.1-70b` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
|
165
165
|
| [Cerebras](/providers/ai-sdk-providers/cerebras) | `llama3.3-70b` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.266",
|
|
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.181",
|
|
49
49
|
"@ai-sdk/provider": "3.0.15",
|
|
50
|
-
"@ai-sdk/provider-utils": "4.0.
|
|
50
|
+
"@ai-sdk/provider-utils": "4.0.48"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@edge-runtime/vm": "^5.0.0",
|
|
@@ -576,6 +576,7 @@ export async function generateText<
|
|
|
576
576
|
const {
|
|
577
577
|
approvedToolApprovals: localApprovedToolApprovals,
|
|
578
578
|
deniedToolApprovals: revalidationDeniedToolApprovals,
|
|
579
|
+
invalidToolApprovals,
|
|
579
580
|
} = await validateApprovedToolApprovals<TOOLS>({
|
|
580
581
|
approvedToolApprovals: approvedToolApprovals.filter(
|
|
581
582
|
toolApproval => !toolApproval.toolCall.providerExecuted,
|
|
@@ -593,7 +594,8 @@ export async function generateText<
|
|
|
593
594
|
|
|
594
595
|
if (
|
|
595
596
|
deniedToolApprovals.length > 0 ||
|
|
596
|
-
localApprovedToolApprovals.length > 0
|
|
597
|
+
localApprovedToolApprovals.length > 0 ||
|
|
598
|
+
invalidToolApprovals.length > 0
|
|
597
599
|
) {
|
|
598
600
|
const toolOutputs = await executeTools({
|
|
599
601
|
toolCalls: localApprovedToolApprovals.map(
|
|
@@ -642,6 +644,24 @@ export async function generateText<
|
|
|
642
644
|
});
|
|
643
645
|
}
|
|
644
646
|
|
|
647
|
+
// Report invalid approved tool calls to the model without executing
|
|
648
|
+
// them. Repairing the input after approval would change the operation
|
|
649
|
+
// that the user authorized.
|
|
650
|
+
for (const toolApproval of invalidToolApprovals) {
|
|
651
|
+
toolContent.push({
|
|
652
|
+
type: 'tool-result' as const,
|
|
653
|
+
toolCallId: toolApproval.toolCall.toolCallId,
|
|
654
|
+
toolName: toolApproval.toolCall.toolName,
|
|
655
|
+
output: await createToolModelOutput({
|
|
656
|
+
toolCallId: toolApproval.toolCall.toolCallId,
|
|
657
|
+
input: toolApproval.toolCall.input,
|
|
658
|
+
tool: tools?.[toolApproval.toolCall.toolName],
|
|
659
|
+
output: toolApproval.error,
|
|
660
|
+
errorMode: 'text',
|
|
661
|
+
}),
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
645
665
|
// add execution denied tool results for all denied tool approvals:
|
|
646
666
|
for (const toolApproval of deniedToolApprovals) {
|
|
647
667
|
toolContent.push({
|
|
@@ -759,6 +759,10 @@ class DefaultStreamTextResult<
|
|
|
759
759
|
|
|
760
760
|
private readonly addStream: (
|
|
761
761
|
stream: ReadableStream<TextStreamPart<TOOLS>>,
|
|
762
|
+
callbacks?: {
|
|
763
|
+
onError?: (error: unknown) => void;
|
|
764
|
+
onCancel?: () => void;
|
|
765
|
+
},
|
|
762
766
|
) => void;
|
|
763
767
|
|
|
764
768
|
private readonly closeStream: () => void;
|
|
@@ -1468,6 +1472,7 @@ class DefaultStreamTextResult<
|
|
|
1468
1472
|
const {
|
|
1469
1473
|
approvedToolApprovals: localApprovedToolApprovals,
|
|
1470
1474
|
deniedToolApprovals: revalidationDeniedToolApprovals,
|
|
1475
|
+
invalidToolApprovals,
|
|
1471
1476
|
} = await validateApprovedToolApprovals<TOOLS>({
|
|
1472
1477
|
approvedToolApprovals: approvedToolApprovals.filter(
|
|
1473
1478
|
toolApproval => !toolApproval.toolCall.providerExecuted,
|
|
@@ -1515,6 +1520,23 @@ class DefaultStreamTextResult<
|
|
|
1515
1520
|
} as StaticToolOutputDenied<TOOLS>);
|
|
1516
1521
|
}
|
|
1517
1522
|
|
|
1523
|
+
for (const toolApproval of invalidToolApprovals) {
|
|
1524
|
+
toolExecutionStepStreamController?.enqueue({
|
|
1525
|
+
type: 'tool-error',
|
|
1526
|
+
toolCallId: toolApproval.toolCall.toolCallId,
|
|
1527
|
+
toolName: toolApproval.toolCall.toolName,
|
|
1528
|
+
input: toolApproval.toolCall.input,
|
|
1529
|
+
error: getErrorMessage(toolApproval.error),
|
|
1530
|
+
title: toolApproval.toolCall.title,
|
|
1531
|
+
...(toolApproval.toolCall.dynamic === true
|
|
1532
|
+
? { dynamic: true as const }
|
|
1533
|
+
: {}),
|
|
1534
|
+
...(toolApproval.toolCall.toolMetadata != null
|
|
1535
|
+
? { toolMetadata: toolApproval.toolCall.toolMetadata }
|
|
1536
|
+
: {}),
|
|
1537
|
+
} as TextStreamPart<TOOLS>);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1518
1540
|
const toolOutputs: Array<ToolOutput<TOOLS>> = [];
|
|
1519
1541
|
|
|
1520
1542
|
await Promise.all(
|
|
@@ -1552,7 +1574,11 @@ class DefaultStreamTextResult<
|
|
|
1552
1574
|
);
|
|
1553
1575
|
|
|
1554
1576
|
// Local tool results (approved + denied) are sent as tool results:
|
|
1555
|
-
if (
|
|
1577
|
+
if (
|
|
1578
|
+
toolOutputs.length > 0 ||
|
|
1579
|
+
localDeniedToolApprovals.length > 0 ||
|
|
1580
|
+
invalidToolApprovals.length > 0
|
|
1581
|
+
) {
|
|
1556
1582
|
const localToolContent: ToolContent = [];
|
|
1557
1583
|
|
|
1558
1584
|
// add regular tool results for approved tool calls:
|
|
@@ -1574,6 +1600,24 @@ class DefaultStreamTextResult<
|
|
|
1574
1600
|
});
|
|
1575
1601
|
}
|
|
1576
1602
|
|
|
1603
|
+
// Report invalid approved tool calls to the model without
|
|
1604
|
+
// executing them. Repairing the input after approval would change
|
|
1605
|
+
// the operation that the user authorized.
|
|
1606
|
+
for (const toolApproval of invalidToolApprovals) {
|
|
1607
|
+
localToolContent.push({
|
|
1608
|
+
type: 'tool-result' as const,
|
|
1609
|
+
toolCallId: toolApproval.toolCall.toolCallId,
|
|
1610
|
+
toolName: toolApproval.toolCall.toolName,
|
|
1611
|
+
output: await createToolModelOutput({
|
|
1612
|
+
toolCallId: toolApproval.toolCall.toolCallId,
|
|
1613
|
+
input: toolApproval.toolCall.input,
|
|
1614
|
+
tool: tools?.[toolApproval.toolCall.toolName],
|
|
1615
|
+
output: toolApproval.error,
|
|
1616
|
+
errorMode: 'text',
|
|
1617
|
+
}),
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1577
1621
|
// add execution denied tool results for denied local tool approvals:
|
|
1578
1622
|
for (const toolApproval of localDeniedToolApprovals) {
|
|
1579
1623
|
localToolContent.push({
|
|
@@ -1645,12 +1689,23 @@ class DefaultStreamTextResult<
|
|
|
1645
1689
|
}
|
|
1646
1690
|
}
|
|
1647
1691
|
|
|
1692
|
+
function clearStepTimeouts() {
|
|
1693
|
+
clearStepTimeout();
|
|
1694
|
+
clearChunkTimeout();
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
function cleanupStepTimeouts() {
|
|
1698
|
+
abortSignal?.removeEventListener('abort', cleanupStepTimeouts);
|
|
1699
|
+
clearStepTimeouts();
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1648
1702
|
// The step's stream is registered lazily and consumed long after this
|
|
1649
|
-
// function returns, so
|
|
1650
|
-
//
|
|
1651
|
-
//
|
|
1652
|
-
abortSignal?.addEventListener('abort',
|
|
1653
|
-
|
|
1703
|
+
// function returns, so its timers must stay armed past setup. When the
|
|
1704
|
+
// merged abort signal fires, drop all step-scoped timers so none
|
|
1705
|
+
// outlives the step.
|
|
1706
|
+
abortSignal?.addEventListener('abort', cleanupStepTimeouts, {
|
|
1707
|
+
once: true,
|
|
1708
|
+
});
|
|
1654
1709
|
|
|
1655
1710
|
try {
|
|
1656
1711
|
stepFinish = new DelayedPromise<void>();
|
|
@@ -2135,8 +2190,7 @@ class DefaultStreamTextResult<
|
|
|
2135
2190
|
});
|
|
2136
2191
|
|
|
2137
2192
|
doStreamSpan.end();
|
|
2138
|
-
|
|
2139
|
-
clearChunkTimeout();
|
|
2193
|
+
cleanupStepTimeouts();
|
|
2140
2194
|
self.closeStream();
|
|
2141
2195
|
return;
|
|
2142
2196
|
}
|
|
@@ -2285,9 +2339,8 @@ class DefaultStreamTextResult<
|
|
|
2285
2339
|
}
|
|
2286
2340
|
}
|
|
2287
2341
|
|
|
2288
|
-
// Clear
|
|
2289
|
-
|
|
2290
|
-
clearChunkTimeout();
|
|
2342
|
+
// Clear this step's timeouts before the next step is started.
|
|
2343
|
+
cleanupStepTimeouts();
|
|
2291
2344
|
|
|
2292
2345
|
if (
|
|
2293
2346
|
// Continue if:
|
|
@@ -2339,12 +2392,15 @@ class DefaultStreamTextResult<
|
|
|
2339
2392
|
},
|
|
2340
2393
|
}),
|
|
2341
2394
|
),
|
|
2395
|
+
{
|
|
2396
|
+
onError: cleanupStepTimeouts,
|
|
2397
|
+
onCancel: cleanupStepTimeouts,
|
|
2398
|
+
},
|
|
2342
2399
|
);
|
|
2343
2400
|
} catch (error) {
|
|
2344
2401
|
// Setup failed before the stream was registered, so neither the
|
|
2345
2402
|
// stream's flush nor an abort will clear the timers — clear them here.
|
|
2346
|
-
|
|
2347
|
-
clearChunkTimeout();
|
|
2403
|
+
cleanupStepTimeouts();
|
|
2348
2404
|
throw error;
|
|
2349
2405
|
}
|
|
2350
2406
|
}
|
|
@@ -17,9 +17,11 @@ import type { ToolSet } from './tool-set';
|
|
|
17
17
|
* input against the tool's input schema, and re-resolves whether the tool
|
|
18
18
|
* actually requires approval.
|
|
19
19
|
*
|
|
20
|
-
* Approvals that fail signature
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* Approvals that fail signature validation throw (fail-closed). Approvals with
|
|
21
|
+
* invalid tool input are returned separately so the model can recover without
|
|
22
|
+
* executing a different operation. Approvals for tools that no longer require
|
|
23
|
+
* approval are moved to the denied list, since the server would never have
|
|
24
|
+
* issued an approval request for them.
|
|
23
25
|
*/
|
|
24
26
|
export async function validateApprovedToolApprovals<TOOLS extends ToolSet>({
|
|
25
27
|
approvedToolApprovals,
|
|
@@ -36,9 +38,15 @@ export async function validateApprovedToolApprovals<TOOLS extends ToolSet>({
|
|
|
36
38
|
}): Promise<{
|
|
37
39
|
approvedToolApprovals: Array<CollectedToolApprovals<TOOLS>>;
|
|
38
40
|
deniedToolApprovals: Array<CollectedToolApprovals<TOOLS>>;
|
|
41
|
+
invalidToolApprovals: Array<
|
|
42
|
+
CollectedToolApprovals<TOOLS> & { error: InvalidToolInputError }
|
|
43
|
+
>;
|
|
39
44
|
}> {
|
|
40
45
|
const approved: Array<CollectedToolApprovals<TOOLS>> = [];
|
|
41
46
|
const denied: Array<CollectedToolApprovals<TOOLS>> = [];
|
|
47
|
+
const invalid: Array<
|
|
48
|
+
CollectedToolApprovals<TOOLS> & { error: InvalidToolInputError }
|
|
49
|
+
> = [];
|
|
42
50
|
|
|
43
51
|
for (const approval of approvedToolApprovals) {
|
|
44
52
|
const { toolCall, approvalRequest } = approval;
|
|
@@ -84,11 +92,15 @@ export async function validateApprovedToolApprovals<TOOLS extends ToolSet>({
|
|
|
84
92
|
});
|
|
85
93
|
|
|
86
94
|
if (!validation.success) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
invalid.push({
|
|
96
|
+
...approval,
|
|
97
|
+
error: new InvalidToolInputError({
|
|
98
|
+
toolName: toolCall.toolName,
|
|
99
|
+
toolInput: JSON.stringify(toolCall.input),
|
|
100
|
+
cause: validation.error,
|
|
101
|
+
}),
|
|
91
102
|
});
|
|
103
|
+
continue;
|
|
92
104
|
}
|
|
93
105
|
}
|
|
94
106
|
|
|
@@ -120,5 +132,9 @@ export async function validateApprovedToolApprovals<TOOLS extends ToolSet>({
|
|
|
120
132
|
}
|
|
121
133
|
}
|
|
122
134
|
|
|
123
|
-
return {
|
|
135
|
+
return {
|
|
136
|
+
approvedToolApprovals: approved,
|
|
137
|
+
deniedToolApprovals: denied,
|
|
138
|
+
invalidToolApprovals: invalid,
|
|
139
|
+
};
|
|
124
140
|
}
|
|
@@ -12,6 +12,7 @@ export function createStitchableStream<T>(): {
|
|
|
12
12
|
innerStream: ReadableStream<T>,
|
|
13
13
|
callbacks?: {
|
|
14
14
|
onError?: (error: unknown) => void;
|
|
15
|
+
onCancel?: () => void;
|
|
15
16
|
},
|
|
16
17
|
) => void;
|
|
17
18
|
close: () => void;
|
|
@@ -20,6 +21,7 @@ export function createStitchableStream<T>(): {
|
|
|
20
21
|
let innerStreams: Array<{
|
|
21
22
|
reader: ReadableStreamDefaultReader<T>;
|
|
22
23
|
onError?: (error: unknown) => void;
|
|
24
|
+
onCancel?: () => void;
|
|
23
25
|
}> = [];
|
|
24
26
|
let controller: ReadableStreamDefaultController<T> | null = null;
|
|
25
27
|
let isClosed = false;
|
|
@@ -29,7 +31,10 @@ export function createStitchableStream<T>(): {
|
|
|
29
31
|
isClosed = true;
|
|
30
32
|
waitForNewStream.resolve();
|
|
31
33
|
|
|
32
|
-
innerStreams.forEach(({ reader }) =>
|
|
34
|
+
innerStreams.forEach(({ reader, onCancel }) => {
|
|
35
|
+
onCancel?.();
|
|
36
|
+
reader.cancel();
|
|
37
|
+
});
|
|
33
38
|
innerStreams = [];
|
|
34
39
|
controller?.close();
|
|
35
40
|
};
|
|
@@ -83,7 +88,8 @@ export function createStitchableStream<T>(): {
|
|
|
83
88
|
},
|
|
84
89
|
pull: processPull,
|
|
85
90
|
async cancel() {
|
|
86
|
-
for (const { reader } of innerStreams) {
|
|
91
|
+
for (const { reader, onCancel } of innerStreams) {
|
|
92
|
+
onCancel?.();
|
|
87
93
|
await reader.cancel();
|
|
88
94
|
}
|
|
89
95
|
innerStreams = [];
|
|
@@ -94,6 +100,7 @@ export function createStitchableStream<T>(): {
|
|
|
94
100
|
innerStream: ReadableStream<T>,
|
|
95
101
|
callbacks?: {
|
|
96
102
|
onError?: (error: unknown) => void;
|
|
103
|
+
onCancel?: () => void;
|
|
97
104
|
},
|
|
98
105
|
) => {
|
|
99
106
|
if (isClosed) {
|