ai 6.0.264 → 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.
@@ -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.264" : "0.0.0-test";
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 ({
@@ -144,7 +144,7 @@ import {
144
144
  } from "@ai-sdk/provider-utils";
145
145
 
146
146
  // src/version.ts
147
- var VERSION = true ? "6.0.264" : "0.0.0-test";
147
+ var VERSION = true ? "6.0.266" : "0.0.0-test";
148
148
 
149
149
  // src/util/download/download.ts
150
150
  var download = async ({
@@ -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-chat` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
162
- | [DeepSeek](/providers/ai-sdk-providers/deepseek) | `deepseek-reasoner` | <Cross size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
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.264",
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.179",
48
+ "@ai-sdk/gateway": "3.0.181",
49
49
  "@ai-sdk/provider": "3.0.15",
50
- "@ai-sdk/provider-utils": "4.0.46"
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 (toolOutputs.length > 0 || localDeniedToolApprovals.length > 0) {
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 the step timer must stay armed past setup. When
1650
- // the merged abort signal fires (any step/chunk/total timeout or caller
1651
- // abort), drop both step-scoped timers so neither outlives the step.
1652
- abortSignal?.addEventListener('abort', clearStepTimeout);
1653
- abortSignal?.addEventListener('abort', clearChunkTimeout);
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
- clearStepTimeout();
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 the step and chunk timeouts before the next step is started
2289
- clearStepTimeout();
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
- clearStepTimeout();
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 or schema validation throw (fail-closed).
21
- * Approvals for tools that no longer require approval are moved to the denied
22
- * list, since the server would never have issued an approval request for them.
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
- throw new InvalidToolInputError({
88
- toolName: toolCall.toolName,
89
- toolInput: JSON.stringify(toolCall.input),
90
- cause: validation.error,
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 { approvedToolApprovals: approved, deniedToolApprovals: denied };
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 }) => reader.cancel());
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) {