ai 7.0.44 → 7.0.45

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.
@@ -85,7 +85,7 @@ import {
85
85
  } from "@ai-sdk/provider-utils";
86
86
 
87
87
  // src/version.ts
88
- var VERSION = true ? "7.0.44" : "0.0.0-test";
88
+ var VERSION = true ? "7.0.45" : "0.0.0-test";
89
89
 
90
90
  // src/util/download/download.ts
91
91
  var download = async ({
@@ -415,16 +415,22 @@ console.log(result.reasoningText);
415
415
 
416
416
  ## Error Handling
417
417
 
418
- When `generateText` with structured output cannot generate a valid object, it throws a [`AI_NoObjectGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-object-generated-error).
418
+ `generateText` can report structured output failures in two ways:
419
419
 
420
- This error occurs when the AI provider fails to generate a parsable object that conforms to the schema.
421
- It can arise due to the following reasons:
420
+ - If the model response cannot be parsed or validated against the schema,
421
+ `generateText` rejects with an
422
+ [`AI_NoObjectGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-object-generated-error).
423
+ - If `generateText` returns a result without an output, accessing `result.output`
424
+ throws an
425
+ [`AI_NoOutputGeneratedError`](/docs/reference/ai-sdk-errors/ai-no-output-generated-error).
426
+ This can happen when the final step does not finish with a `stop` reason, for
427
+ example when it finishes with `tool-calls`.
422
428
 
423
- - The model failed to generate a response.
424
- - The model generated a response that could not be parsed.
425
- - The model generated a response that could not be validated against the schema.
429
+ The `output` property is a getter, so destructuring it also triggers this
430
+ access.
426
431
 
427
- The error preserves the following information to help you log the issue:
432
+ `NoObjectGeneratedError` preserves the following information to help you log
433
+ the issue:
428
434
 
429
435
  - `text`: The text that was generated by the model. This can be the raw text or the tool call text, depending on the object generation mode.
430
436
  - `response`: Metadata about the language model response, including response id, timestamp, and model.
@@ -432,14 +438,21 @@ The error preserves the following information to help you log the issue:
432
438
  - `cause`: The cause of the error (e.g. a JSON parsing error). You can use this for more detailed error handling.
433
439
 
434
440
  ```ts
435
- import { generateText, Output, NoObjectGeneratedError } from 'ai';
441
+ import {
442
+ generateText,
443
+ NoObjectGeneratedError,
444
+ NoOutputGeneratedError,
445
+ Output,
446
+ } from 'ai';
436
447
 
437
448
  try {
438
- await generateText({
449
+ const result = await generateText({
439
450
  model,
440
451
  output: Output.object({ schema }),
441
452
  prompt,
442
453
  });
454
+
455
+ console.log(result.output);
443
456
  } catch (error) {
444
457
  if (NoObjectGeneratedError.isInstance(error)) {
445
458
  console.log('NoObjectGeneratedError');
@@ -447,6 +460,8 @@ try {
447
460
  console.log('Text:', error.text);
448
461
  console.log('Response:', error.response);
449
462
  console.log('Usage:', error.usage);
463
+ } else if (NoOutputGeneratedError.isInstance(error)) {
464
+ console.log('NoOutputGeneratedError');
450
465
  }
451
466
  }
452
467
  ```
@@ -2822,10 +2822,9 @@ To see `generateText` in action, check out [these examples](#examples).
2822
2822
  },
2823
2823
  {
2824
2824
  name: 'output',
2825
- type: 'Output',
2826
- isOptional: true,
2825
+ type: 'InferCompleteOutput<OUTPUT>',
2827
2826
  description:
2828
- 'The generated structured output. It uses the `output` specification.',
2827
+ 'The generated output according to the `output` specification. Accessing this property throws `NoOutputGeneratedError` when no output is available, for example when the final step does not finish with a `stop` reason.',
2829
2828
  },
2830
2829
  {
2831
2830
  name: 'steps',
@@ -622,6 +622,13 @@ To see `streamText` in action, check out [these examples](#examples).
622
622
  description:
623
623
  "Approval configuration for this call. Pass a `GenericToolApprovalFunction` to handle all tool calls in one callback with `toolCall`, `tools`, `toolsContext`, `messages`, and `runtimeContext`, or pass a per-tool object where each key can be a status (`'not-applicable'`, `'approved'`, `'denied'`, or `'user-approval'`), an object form such as `{ type: 'denied', reason: 'blocked by policy' }`, or a `SingleToolApprovalFunction` that receives the tool input and options `toolCallId`, `messages`, `toolContext`, and `runtimeContext` (same shape as tool execution options without `abortSignal`, with `context` renamed to `toolContext`). The `RUNTIME_CONTEXT` type parameter matches the call's `runtimeContext`. A `GenericToolApprovalFunction` or `SingleToolApprovalFunction` may return `undefined` for the same effect as `'not-applicable'`. `'not-applicable'` is the default execution path and runs the tool without approval metadata. Use `'approved'`, `'denied'`, or their object forms when you want explicit automatic approval request/response parts in the output. Automatic approvals and denials can include a `reason`, which is forwarded to the emitted approval response. This setting takes precedence over a tool's `needsApproval` default.",
624
624
  },
625
+ {
626
+ name: 'experimental_toolCallers',
627
+ type: 'Experimental_ToolCallers<TOOLS>',
628
+ isOptional: true,
629
+ description:
630
+ "Configures which caller tools may invoke each tool. The callback receives typed references for caller-capable tools in the `tools` set and returns an object keyed by callee tool name. Include `'direct'` to keep a configured tool directly callable by the model. Local-only callees are hidden from direct model calls and bound to their local caller for each generation step. Provider caller references are translated to provider-native allowed-caller options. Tools without an entry keep their existing direct tool-calling behavior.",
631
+ },
625
632
  {
626
633
  name: 'experimental_refineToolInput',
627
634
  type: 'ToolInputRefinement<TOOLS>',
@@ -111,6 +111,13 @@ To see `ToolLoopAgent` in action, check out [these examples](#examples).
111
111
  description:
112
112
  "Approval configuration for the agent. Pass a `GenericToolApprovalFunction` to handle all tool calls in one callback with `toolCall`, `tools`, `toolsContext`, `messages`, and `runtimeContext`, or pass a per-tool object where each key can be a status (`'not-applicable'`, `'approved'`, `'denied'`, or `'user-approval'`), an object form such as `{ type: 'denied', reason: 'blocked by policy' }`, or a `SingleToolApprovalFunction` that receives the tool input and options `toolCallId`, `messages`, `toolContext`, and `runtimeContext` (same shape as tool execution options without `abortSignal`, with `context` renamed to `toolContext`). The `RUNTIME_CONTEXT` type parameter matches the agent's `runtimeContext`. A `GenericToolApprovalFunction` or `SingleToolApprovalFunction` may return `undefined` for the same effect as `'not-applicable'`. `'not-applicable'` is the default execution path and runs the tool without approval metadata. Use `'approved'`, `'denied'`, or their object forms when you want explicit automatic approval request/response parts in the output. Automatic approvals and denials can include a `reason`, which is forwarded to the emitted approval response. This setting takes precedence over a tool's `needsApproval` default.",
113
113
  },
114
+ {
115
+ name: 'experimental_toolCallers',
116
+ type: 'Experimental_ToolCallers<TOOLS>',
117
+ isOptional: true,
118
+ description:
119
+ "Configures which caller tools may invoke each tool. The callback receives typed references for caller-capable tools in the agent's `tools` set and returns an object keyed by callee tool name. Include `'direct'` to keep a configured tool directly callable by the model. Local-only callees are hidden from direct model calls and bound to their local caller for each agent step. Provider caller references are translated to provider-native allowed-caller options.",
120
+ },
114
121
  {
115
122
  name: 'output',
116
123
  type: 'Output',
@@ -7,6 +7,11 @@ description: Learn how to fix AI_NoOutputGeneratedError
7
7
 
8
8
  This error is thrown when no LLM output was generated, e.g. because of errors.
9
9
 
10
+ For `generateText`, accessing `result.output` throws this error when the result
11
+ does not contain an output. This can happen when the final step does not finish
12
+ with a `stop` reason, for example when it finishes with `tool-calls`. The
13
+ `output` property is a getter, so destructuring it also triggers this access.
14
+
10
15
  ## Properties
11
16
 
12
17
  - `message`: The error message (optional, defaults to `'No output generated.'`)
@@ -2072,11 +2072,48 @@ import { useAssistant } from '@ai-sdk/react';
2072
2072
  ```
2073
2073
 
2074
2074
  ```tsx filename="AI SDK 5.0"
2075
- // useAssistant has been removed
2076
- // Use useChat with appropriate configuration instead
2075
+ import { useChat } from '@ai-sdk/react';
2076
+ import { DefaultChatTransport } from 'ai';
2077
+
2078
+ function Chat() {
2079
+ const { messages, sendMessage } = useChat({
2080
+ transport: new DefaultChatTransport({
2081
+ api: '/api/chat',
2082
+ }),
2083
+ });
2084
+
2085
+ // ...
2086
+ }
2077
2087
  ```
2078
2088
 
2079
- For an implementation of the assistant functionality with AI SDK v5, see this [example repository](https://github.com/vercel-labs/ai-sdk-openai-assistants-api).
2089
+ The `useAssistant` hook was specific to the OpenAI Assistants API. OpenAI has
2090
+ deprecated that API in favor of the Responses API. Configure `useChat` for your
2091
+ route as shown above, then return a UI message stream from the route:
2092
+
2093
+ ```tsx filename="app/api/chat/route.ts"
2094
+ import { openai } from '@ai-sdk/openai';
2095
+ import { convertToModelMessages, streamText, type UIMessage } from 'ai';
2096
+
2097
+ export async function POST(req: Request) {
2098
+ const { messages }: { messages: UIMessage[] } = await req.json();
2099
+
2100
+ const result = streamText({
2101
+ model: openai.responses('gpt-4o-mini'),
2102
+ prompt: convertToModelMessages(messages),
2103
+ });
2104
+
2105
+ return result.toUIMessageStreamResponse();
2106
+ }
2107
+ ```
2108
+
2109
+ For persistent conversation state and built-in tools, see the
2110
+ [OpenAI Responses API guide](/cookbook/guides/openai-responses).
2111
+
2112
+ If you need to connect `useChat` to another backend, see the
2113
+ [transport documentation](/docs/ai-sdk-ui/transport) and
2114
+ [stream protocol](/docs/ai-sdk-ui/stream-protocol). For migrating existing
2115
+ OpenAI Assistants data and API calls, see OpenAI's
2116
+ [Assistants migration guide](https://platform.openai.com/docs/assistants/migration).
2080
2117
 
2081
2118
  #### Attachments → File Parts
2082
2119
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "7.0.44",
3
+ "version": "7.0.45",
4
4
  "type": "module",
5
5
  "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.",
6
6
  "license": "Apache-2.0",
@@ -42,9 +42,9 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@ai-sdk/gateway": "4.0.33",
45
+ "@ai-sdk/gateway": "4.0.34",
46
46
  "@ai-sdk/provider": "4.0.4",
47
- "@ai-sdk/provider-utils": "5.0.16"
47
+ "@ai-sdk/provider-utils": "5.0.17"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@edge-runtime/vm": "^5.0.0",
@@ -22,6 +22,7 @@ import type { PrepareStepFunction } from '../generate-text/prepare-step';
22
22
  import type { StopCondition } from '../generate-text/stop-condition';
23
23
  import type { StreamTextInclude } from '../generate-text/stream-text';
24
24
  import type { ToolApprovalConfiguration } from '../generate-text/tool-approval-configuration';
25
+ import type { Experimental_ToolCallers } from '../generate-text/tool-caller-configuration';
25
26
  import type { ToolCallRepairFunction } from '../generate-text/tool-call-repair-function';
26
27
  import type {
27
28
  OnToolExecutionEndCallback,
@@ -134,6 +135,11 @@ export type ToolLoopAgentSettings<
134
135
  */
135
136
  toolApproval?: ToolApprovalConfiguration<NoInfer<TOOLS>, RUNTIME_CONTEXT>;
136
137
 
138
+ /**
139
+ * Configures which caller tools may invoke each tool.
140
+ */
141
+ experimental_toolCallers?: Experimental_ToolCallers<NoInfer<TOOLS>>;
142
+
137
143
  /**
138
144
  * Optional function that you can use to provide different settings for a step.
139
145
  */
@@ -329,6 +335,7 @@ export type ToolLoopAgentSettings<
329
335
  | 'activeTools'
330
336
  | 'toolOrder'
331
337
  | 'toolApproval'
338
+ | 'experimental_toolCallers'
332
339
  | 'providerOptions'
333
340
  | 'experimental_download'
334
341
  | 'experimental_refineToolInput'
@@ -363,6 +370,7 @@ export type ToolLoopAgentSettings<
363
370
  | 'activeTools'
364
371
  | 'toolOrder'
365
372
  | 'toolApproval'
373
+ | 'experimental_toolCallers'
366
374
  | 'providerOptions'
367
375
  | 'experimental_download'
368
376
  | 'experimental_refineToolInput'
@@ -172,8 +172,10 @@ export interface GenerateTextResult<
172
172
  readonly finalStep: StepResult<TOOLS, RUNTIME_CONTEXT>;
173
173
 
174
174
  /**
175
- * The generated structured output. It uses the `output` specification.
175
+ * The generated output according to the `output` specification.
176
176
  *
177
+ * @throws {NoOutputGeneratedError} When no output is available, for example
178
+ * when the final step does not finish with a `stop` reason.
177
179
  */
178
180
  readonly output: InferCompleteOutput<OUTPUT>;
179
181
  }
@@ -30,6 +30,8 @@ import { prepareToolChoice } from '../prompt/prepare-tool-choice';
30
30
  import { prepareTools } from '../prompt/prepare-tools';
31
31
  import type { Prompt } from '../prompt/prompt';
32
32
  import {
33
+ getChunkTimeoutMs,
34
+ getFirstChunkTimeoutMs,
33
35
  getStepTimeoutMs,
34
36
  getTotalTimeoutMs,
35
37
  type RequestOptions,
@@ -43,6 +45,7 @@ import type {
43
45
  LanguageModel,
44
46
  LanguageModelRequestMetadata,
45
47
  ToolChoice,
48
+ Warning,
46
49
  } from '../types';
47
50
  import {
48
51
  addLanguageModelUsage,
@@ -588,6 +591,33 @@ export async function generateText<
588
591
  onToolExecutionEnd ?? experimental_onToolCallFinish;
589
592
  const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
590
593
 
594
+ const unsupportedTimeoutWarnings: Warning[] = [];
595
+
596
+ if (getFirstChunkTimeoutMs(timeout) != null) {
597
+ unsupportedTimeoutWarnings.push({
598
+ type: 'unsupported',
599
+ feature: 'timeout.firstChunkMs',
600
+ details:
601
+ 'The firstChunkMs timeout is only supported by streaming functions.',
602
+ });
603
+ }
604
+
605
+ if (getChunkTimeoutMs(timeout) != null) {
606
+ unsupportedTimeoutWarnings.push({
607
+ type: 'unsupported',
608
+ feature: 'timeout.chunkMs',
609
+ details: 'The chunkMs timeout is only supported by streaming functions.',
610
+ });
611
+ }
612
+
613
+ if (unsupportedTimeoutWarnings.length > 0) {
614
+ logWarnings({
615
+ warnings: unsupportedTimeoutWarnings,
616
+ provider: model.provider,
617
+ model: model.modelId,
618
+ });
619
+ }
620
+
591
621
  const totalTimeoutMs = getTotalTimeoutMs(timeout);
592
622
  const stepTimeoutMs = getStepTimeoutMs(timeout);
593
623
  const stepAbortController =
@@ -136,6 +136,11 @@ import type {
136
136
  } from './stream-text-result';
137
137
  import { toResponseMessages } from './to-response-messages';
138
138
  import type { ToolApprovalConfiguration } from './tool-approval-configuration';
139
+ import {
140
+ prepareToolsForToolCallers,
141
+ resolveToolCallerConfiguration,
142
+ type Experimental_ToolCallers,
143
+ } from './tool-caller-configuration';
139
144
  import type { TypedToolCall } from './tool-call';
140
145
  import type { ToolCallRepairFunction } from './tool-call-repair-function';
141
146
  import type {
@@ -372,6 +377,7 @@ export function streamText<
372
377
  experimental_sandbox: sandbox,
373
378
  output,
374
379
  toolApproval,
380
+ experimental_toolCallers,
375
381
  experimental_toolApprovalSecret,
376
382
  experimental_telemetry,
377
383
  telemetry = experimental_telemetry,
@@ -495,6 +501,11 @@ export function streamText<
495
501
  */
496
502
  toolApproval?: ToolApprovalConfiguration<TOOLS, RUNTIME_CONTEXT>;
497
503
 
504
+ /**
505
+ * Configures which caller tools may invoke each tool.
506
+ */
507
+ experimental_toolCallers?: Experimental_ToolCallers<NoInfer<TOOLS>>;
508
+
498
509
  /**
499
510
  * Secret for HMAC-signing tool approval requests. When set, the server
500
511
  * signs each approval request at issuance and verifies the signature when
@@ -795,6 +806,7 @@ export function streamText<
795
806
  stopConditions: asArray(stopWhen),
796
807
  output,
797
808
  toolApproval,
809
+ experimental_toolCallers,
798
810
  experimental_toolApprovalSecret,
799
811
  providerOptions,
800
812
  prepareStep,
@@ -1009,6 +1021,7 @@ class DefaultStreamTextResult<
1009
1021
  stopConditions,
1010
1022
  output,
1011
1023
  toolApproval,
1024
+ experimental_toolCallers,
1012
1025
  experimental_toolApprovalSecret,
1013
1026
  providerOptions,
1014
1027
  prepareStep,
@@ -1064,6 +1077,7 @@ class DefaultStreamTextResult<
1064
1077
  >;
1065
1078
  output: OUTPUT | undefined;
1066
1079
  toolApproval: ToolApprovalConfiguration<TOOLS, RUNTIME_CONTEXT> | undefined;
1080
+ experimental_toolCallers: Experimental_ToolCallers<TOOLS> | undefined;
1067
1081
  experimental_toolApprovalSecret: string | Uint8Array | undefined;
1068
1082
  providerOptions: ProviderOptions | undefined;
1069
1083
  prepareStep:
@@ -1114,6 +1128,10 @@ class DefaultStreamTextResult<
1114
1128
  }) {
1115
1129
  this.outputSpecification = output;
1116
1130
  this.tools = tools;
1131
+ const resolvedToolCallers = resolveToolCallerConfiguration({
1132
+ tools,
1133
+ toolCallers: experimental_toolCallers,
1134
+ });
1117
1135
 
1118
1136
  const telemetryDispatcher = createRestrictedTelemetryDispatcher<
1119
1137
  TOOLS,
@@ -1938,10 +1956,20 @@ class DefaultStreamTextResult<
1938
1956
  tools,
1939
1957
  activeTools: prepareStepResult?.activeTools ?? activeTools,
1940
1958
  });
1959
+ const {
1960
+ executionTools: stepExecutionTools,
1961
+ modelTools: stepModelTools,
1962
+ } = prepareToolsForToolCallers({
1963
+ tools: stepActiveTools,
1964
+ toolCallers: resolvedToolCallers,
1965
+ });
1941
1966
  const stepToolOrder = prepareStepResult?.toolOrder ?? toolOrder;
1942
1967
 
1943
1968
  const stepTools = await prepareTools({
1944
- tools: stepActiveTools,
1969
+ tools: stepModelTools as ActiveToolSubset<
1970
+ TOOLS,
1971
+ ActiveTools<NoInfer<TOOLS>>
1972
+ >,
1945
1973
  toolOrder: stepToolOrder as ToolOrder<
1946
1974
  ActiveToolSubset<TOOLS, ActiveTools<NoInfer<TOOLS>>>
1947
1975
  >,
@@ -1986,7 +2014,7 @@ class DefaultStreamTextResult<
1986
2014
  retry(async () =>
1987
2015
  streamLanguageModelCall({
1988
2016
  model: prepareStepResult?.model ?? model,
1989
- tools: stepActiveTools,
2017
+ tools: stepModelTools as TOOLS,
1990
2018
  toolOrder: stepToolOrder,
1991
2019
  toolChoice: prepareStepResult?.toolChoice ?? toolChoice,
1992
2020
  instructions: stepInstructions,
@@ -2056,7 +2084,7 @@ class DefaultStreamTextResult<
2056
2084
  const streamAfterToolCallbackInvocation =
2057
2085
  invokeToolCallbacksFromStream({
2058
2086
  stream: languageModelStream,
2059
- tools,
2087
+ tools: stepExecutionTools as TOOLS,
2060
2088
  stepInputMessages: stepMessages,
2061
2089
  abortSignal,
2062
2090
  runtimeContext,
@@ -2079,7 +2107,7 @@ class DefaultStreamTextResult<
2079
2107
 
2080
2108
  const streamWithToolResults = executeToolsFromStream({
2081
2109
  stream: streamAfterToolCallbackInvocation,
2082
- tools,
2110
+ tools: stepExecutionTools as TOOLS,
2083
2111
  callId,
2084
2112
  messages: stepMessages,
2085
2113
  abortSignal,
@@ -2360,7 +2388,7 @@ class DefaultStreamTextResult<
2360
2388
  // the client tool's result is sent back.
2361
2389
  for (const toolCall of stepToolCalls) {
2362
2390
  if (toolCall.providerExecuted !== true) continue;
2363
- const tool = getOwn(tools, toolCall.toolName);
2391
+ const tool = getOwn(stepExecutionTools, toolCall.toolName);
2364
2392
  if (
2365
2393
  tool?.type === 'provider' &&
2366
2394
  tool.supportsDeferredResults