@ai-sdk/provider-utils 5.0.0-beta.0 → 5.0.0-beta.10

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.
@@ -18,8 +18,8 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // src/test/index.ts
21
- var test_exports = {};
22
- __export(test_exports, {
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
23
  convertArrayToAsyncIterable: () => convertArrayToAsyncIterable,
24
24
  convertArrayToReadableStream: () => convertArrayToReadableStream,
25
25
  convertAsyncIterableToArray: () => convertAsyncIterableToArray,
@@ -28,7 +28,7 @@ __export(test_exports, {
28
28
  isNodeVersion: () => isNodeVersion,
29
29
  mockId: () => mockId
30
30
  });
31
- module.exports = __toCommonJS(test_exports);
31
+ module.exports = __toCommonJS(index_exports);
32
32
 
33
33
  // src/test/convert-array-to-async-iterable.ts
34
34
  function convertArrayToAsyncIterable(values) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/provider-utils",
3
- "version": "5.0.0-beta.0",
3
+ "version": "5.0.0-beta.10",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -35,7 +35,7 @@
35
35
  "dependencies": {
36
36
  "@standard-schema/spec": "^1.1.0",
37
37
  "eventsource-parser": "^3.0.6",
38
- "@ai-sdk/provider": "4.0.0-beta.0"
38
+ "@ai-sdk/provider": "4.0.0-beta.6"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "20.17.24",
@@ -69,9 +69,7 @@
69
69
  "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
70
70
  "build:watch": "pnpm clean && tsup --watch",
71
71
  "clean": "del-cli dist *.tsbuildinfo",
72
- "lint": "eslint \"./**/*.ts*\"",
73
72
  "type-check": "tsc --build",
74
- "prettier-check": "prettier --check \"./**/*.ts*\"",
75
73
  "test": "pnpm test:node && pnpm test:edge",
76
74
  "test:update": "pnpm test:node -u",
77
75
  "test:watch": "vitest --config vitest.node.config.js",
@@ -1,14 +1,14 @@
1
- import { ImageModelV3File } from '@ai-sdk/provider';
1
+ import { ImageModelV4File } from '@ai-sdk/provider';
2
2
  import { convertUint8ArrayToBase64 } from './uint8-utils';
3
3
 
4
4
  /**
5
- * Convert an ImageModelV3File to a URL or data URI string.
5
+ * Convert an ImageModelV4File to a URL or data URI string.
6
6
  *
7
7
  * If the file is a URL, it returns the URL as-is.
8
8
  * If the file is base64 data, it returns a data URI with the base64 data.
9
9
  * If the file is a Uint8Array, it converts it to base64 and returns a data URI.
10
10
  */
11
- export function convertImageModelFileToDataUri(file: ImageModelV3File): string {
11
+ export function convertImageModelFileToDataUri(file: ImageModelV4File): string {
12
12
  if (file.type === 'url') return file.url;
13
13
 
14
14
  return `data:${file.mediaType};base64,${
@@ -1,6 +1,6 @@
1
1
  import {
2
- LanguageModelV3FunctionTool,
3
- LanguageModelV3ProviderTool,
2
+ LanguageModelV4FunctionTool,
3
+ LanguageModelV4ProviderTool,
4
4
  } from '@ai-sdk/provider';
5
5
 
6
6
  /**
@@ -33,41 +33,25 @@ export interface ToolNameMapping {
33
33
  export function createToolNameMapping({
34
34
  tools = [],
35
35
  providerToolNames,
36
- resolveProviderToolName,
37
36
  }: {
38
37
  /**
39
38
  * Tools that were passed to the language model.
40
39
  */
41
40
  tools:
42
- | Array<LanguageModelV3FunctionTool | LanguageModelV3ProviderTool>
41
+ | Array<LanguageModelV4FunctionTool | LanguageModelV4ProviderTool>
43
42
  | undefined;
44
43
 
45
44
  /**
46
45
  * Maps the provider tool ids to the provider tool names.
47
46
  */
48
47
  providerToolNames: Record<`${string}.${string}`, string>;
49
-
50
- /**
51
- * Optional resolver for provider tool names that cannot be represented as
52
- * static id -> name mappings (e.g. dynamic provider names).
53
- */
54
- resolveProviderToolName?: (
55
- tool: LanguageModelV3ProviderTool,
56
- ) => string | undefined;
57
48
  }): ToolNameMapping {
58
49
  const customToolNameToProviderToolName: Record<string, string> = {};
59
50
  const providerToolNameToCustomToolName: Record<string, string> = {};
60
51
 
61
52
  for (const tool of tools) {
62
- if (tool.type === 'provider') {
63
- const providerToolName =
64
- resolveProviderToolName?.(tool) ??
65
- (tool.id in providerToolNames ? providerToolNames[tool.id] : undefined);
66
-
67
- if (providerToolName == null) {
68
- continue;
69
- }
70
-
53
+ if (tool.type === 'provider' && tool.id in providerToolNames) {
54
+ const providerToolName = providerToolNames[tool.id];
71
55
  customToolNameToProviderToolName[tool.name] = providerToolName;
72
56
  providerToolNameToCustomToolName[providerToolName] = tool.name;
73
57
  }
@@ -26,6 +26,11 @@ export async function downloadBlob(
26
26
  signal: options?.abortSignal,
27
27
  });
28
28
 
29
+ // Validate final URL after redirects to prevent SSRF via open redirect
30
+ if (response.redirected) {
31
+ validateDownloadUrl(response.url);
32
+ }
33
+
29
34
  if (!response.ok) {
30
35
  throw new DownloadError({
31
36
  url,
package/src/index.ts CHANGED
@@ -23,8 +23,14 @@ export { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-a
23
23
  export { injectJsonInstructionIntoMessages } from './inject-json-instruction';
24
24
  export * from './is-abort-error';
25
25
  export { isNonNullable } from './is-non-nullable';
26
+ export { isProviderReference } from './is-provider-reference';
26
27
  export { isUrlSupported } from './is-url-supported';
27
28
  export * from './load-api-key';
29
+ export {
30
+ isCustomReasoning,
31
+ mapReasoningToProviderBudget,
32
+ mapReasoningToProviderEffort,
33
+ } from './map-reasoning-to-provider';
28
34
  export { loadOptionalSetting } from './load-optional-setting';
29
35
  export { loadSetting } from './load-setting';
30
36
  export { type MaybePromiseLike } from './maybe-promise-like';
@@ -41,6 +47,7 @@ export {
41
47
  type ProviderToolFactoryWithOutputSchema,
42
48
  } from './provider-tool-factory';
43
49
  export * from './remove-undefined-entries';
50
+ export { resolveProviderReference } from './resolve-provider-reference';
44
51
  export * from './resolve';
45
52
  export * from './response-handler';
46
53
  export {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  JSONSchema7,
3
- LanguageModelV3Message,
4
- LanguageModelV3Prompt,
3
+ LanguageModelV4Message,
4
+ LanguageModelV4Prompt,
5
5
  } from '@ai-sdk/provider';
6
6
 
7
7
  const DEFAULT_SCHEMA_PREFIX = 'JSON schema:';
@@ -39,12 +39,12 @@ export function injectJsonInstructionIntoMessages({
39
39
  schemaPrefix,
40
40
  schemaSuffix,
41
41
  }: {
42
- messages: LanguageModelV3Prompt;
42
+ messages: LanguageModelV4Prompt;
43
43
  schema?: JSONSchema7;
44
44
  schemaPrefix?: string;
45
45
  schemaSuffix?: string;
46
- }): LanguageModelV3Prompt {
47
- const systemMessage: LanguageModelV3Message =
46
+ }): LanguageModelV4Prompt {
47
+ const systemMessage: LanguageModelV4Message =
48
48
  messages[0]?.role === 'system'
49
49
  ? { ...messages[0] }
50
50
  : { role: 'system', content: '' };
@@ -0,0 +1,18 @@
1
+ import {
2
+ LanguageModelV4FilePart,
3
+ SharedV4ProviderReference,
4
+ } from '@ai-sdk/provider';
5
+
6
+ /**
7
+ * Checks whether file part data is a provider reference (a mapping of provider
8
+ * names to provider-specific identifiers) as opposed to raw bytes or a URL.
9
+ */
10
+ export function isProviderReference(
11
+ data: LanguageModelV4FilePart['data'],
12
+ ): data is SharedV4ProviderReference {
13
+ return (
14
+ typeof data === 'object' &&
15
+ !(data instanceof Uint8Array) &&
16
+ !(data instanceof URL)
17
+ );
18
+ }
@@ -0,0 +1,105 @@
1
+ import { LanguageModelV4CallOptions, SharedV4Warning } from '@ai-sdk/provider';
2
+
3
+ export type ReasoningLevel = Exclude<
4
+ LanguageModelV4CallOptions['reasoning'],
5
+ 'none' | 'provider-default' | undefined
6
+ >;
7
+
8
+ export function isCustomReasoning(
9
+ reasoning: LanguageModelV4CallOptions['reasoning'],
10
+ ): reasoning is Exclude<
11
+ LanguageModelV4CallOptions['reasoning'],
12
+ 'provider-default' | undefined
13
+ > {
14
+ return reasoning !== undefined && reasoning !== 'provider-default';
15
+ }
16
+
17
+ /**
18
+ * Maps a top-level reasoning level to a provider-specific effort string using
19
+ * the given effort map. Pushes a compatibility warning if the reasoning level
20
+ * maps to a different string, or an unsupported warning if the level is not
21
+ * present in the map.
22
+ *
23
+ * @returns The mapped effort string, or `undefined` if the level is not
24
+ * supported.
25
+ */
26
+ export function mapReasoningToProviderEffort<T extends string>({
27
+ reasoning,
28
+ effortMap,
29
+ warnings,
30
+ }: {
31
+ reasoning: ReasoningLevel;
32
+ effortMap: Partial<Record<ReasoningLevel, T>>;
33
+ warnings: SharedV4Warning[];
34
+ }): T | undefined {
35
+ const mapped = effortMap[reasoning];
36
+
37
+ if (mapped == null) {
38
+ warnings.push({
39
+ type: 'unsupported',
40
+ feature: 'reasoning',
41
+ details: `reasoning "${reasoning}" is not supported by this model.`,
42
+ });
43
+ return undefined;
44
+ }
45
+
46
+ if (mapped !== reasoning) {
47
+ warnings.push({
48
+ type: 'compatibility',
49
+ feature: 'reasoning',
50
+ details: `reasoning "${reasoning}" is not directly supported by this model. mapped to effort "${mapped}".`,
51
+ });
52
+ }
53
+
54
+ return mapped;
55
+ }
56
+
57
+ const DEFAULT_REASONING_BUDGET_PERCENTAGES: Record<ReasoningLevel, number> = {
58
+ minimal: 0.02,
59
+ low: 0.1,
60
+ medium: 0.3,
61
+ high: 0.6,
62
+ xhigh: 0.9,
63
+ };
64
+
65
+ /**
66
+ * Maps a top-level reasoning level to an absolute token budget by multiplying
67
+ * the model's max output tokens by a percentage from the budget percentages
68
+ * map. The result is clamped between `minReasoningBudget` (default 1024) and
69
+ * `maxReasoningBudget`. Pushes an unsupported warning if the level is not
70
+ * present in the budget percentages map.
71
+ *
72
+ * @returns The computed token budget, or `undefined` if the level is not
73
+ * supported.
74
+ */
75
+ export function mapReasoningToProviderBudget({
76
+ reasoning,
77
+ maxOutputTokens,
78
+ maxReasoningBudget,
79
+ minReasoningBudget = 1024,
80
+ budgetPercentages = DEFAULT_REASONING_BUDGET_PERCENTAGES,
81
+ warnings,
82
+ }: {
83
+ reasoning: ReasoningLevel;
84
+ maxOutputTokens: number;
85
+ maxReasoningBudget: number;
86
+ minReasoningBudget?: number;
87
+ budgetPercentages?: Partial<Record<ReasoningLevel, number>>;
88
+ warnings: SharedV4Warning[];
89
+ }): number | undefined {
90
+ const pct = budgetPercentages[reasoning];
91
+
92
+ if (pct == null) {
93
+ warnings.push({
94
+ type: 'unsupported',
95
+ feature: 'reasoning',
96
+ details: `reasoning "${reasoning}" is not supported by this model.`,
97
+ });
98
+ return undefined;
99
+ }
100
+
101
+ return Math.min(
102
+ maxReasoningBudget,
103
+ Math.max(minReasoningBudget, Math.round(maxOutputTokens * pct)),
104
+ );
105
+ }
@@ -1,24 +1,33 @@
1
1
  import { tool, Tool, ToolExecuteFunction } from './types/tool';
2
2
  import { FlexibleSchema } from './schema';
3
+ import { Context } from './types/context';
3
4
 
4
- export type ProviderToolFactory<INPUT, ARGS extends object> = <OUTPUT>(
5
+ export type ProviderToolFactory<
6
+ INPUT,
7
+ ARGS extends object,
8
+ CONTEXT extends Context = {},
9
+ > = <OUTPUT>(
5
10
  options: ARGS & {
6
- execute?: ToolExecuteFunction<INPUT, OUTPUT>;
7
- needsApproval?: Tool<INPUT, OUTPUT>['needsApproval'];
8
- toModelOutput?: Tool<INPUT, OUTPUT>['toModelOutput'];
9
- onInputStart?: Tool<INPUT, OUTPUT>['onInputStart'];
10
- onInputDelta?: Tool<INPUT, OUTPUT>['onInputDelta'];
11
- onInputAvailable?: Tool<INPUT, OUTPUT>['onInputAvailable'];
11
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
12
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
13
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
14
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
15
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
16
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
12
17
  },
13
- ) => Tool<INPUT, OUTPUT>;
18
+ ) => Tool<INPUT, OUTPUT, CONTEXT>;
14
19
 
15
- export function createProviderToolFactory<INPUT, ARGS extends object>({
20
+ export function createProviderToolFactory<
21
+ INPUT,
22
+ ARGS extends object,
23
+ CONTEXT extends Context = {},
24
+ >({
16
25
  id,
17
26
  inputSchema,
18
27
  }: {
19
28
  id: `${string}.${string}`;
20
29
  inputSchema: FlexibleSchema<INPUT>;
21
- }): ProviderToolFactory<INPUT, ARGS> {
30
+ }): ProviderToolFactory<INPUT, ARGS, CONTEXT> {
22
31
  return <OUTPUT>({
23
32
  execute,
24
33
  outputSchema,
@@ -29,14 +38,14 @@ export function createProviderToolFactory<INPUT, ARGS extends object>({
29
38
  onInputAvailable,
30
39
  ...args
31
40
  }: ARGS & {
32
- execute?: ToolExecuteFunction<INPUT, OUTPUT>;
41
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
33
42
  outputSchema?: FlexibleSchema<OUTPUT>;
34
- needsApproval?: Tool<INPUT, OUTPUT>['needsApproval'];
35
- toModelOutput?: Tool<INPUT, OUTPUT>['toModelOutput'];
36
- onInputStart?: Tool<INPUT, OUTPUT>['onInputStart'];
37
- onInputDelta?: Tool<INPUT, OUTPUT>['onInputDelta'];
38
- onInputAvailable?: Tool<INPUT, OUTPUT>['onInputAvailable'];
39
- }): Tool<INPUT, OUTPUT> =>
43
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
44
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
45
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
46
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
47
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
48
+ }): Tool<INPUT, OUTPUT, CONTEXT> =>
40
49
  tool({
41
50
  type: 'provider',
42
51
  id,
@@ -56,21 +65,23 @@ export type ProviderToolFactoryWithOutputSchema<
56
65
  INPUT,
57
66
  OUTPUT,
58
67
  ARGS extends object,
68
+ CONTEXT extends Context = {},
59
69
  > = (
60
70
  options: ARGS & {
61
- execute?: ToolExecuteFunction<INPUT, OUTPUT>;
62
- needsApproval?: Tool<INPUT, OUTPUT>['needsApproval'];
63
- toModelOutput?: Tool<INPUT, OUTPUT>['toModelOutput'];
64
- onInputStart?: Tool<INPUT, OUTPUT>['onInputStart'];
65
- onInputDelta?: Tool<INPUT, OUTPUT>['onInputDelta'];
66
- onInputAvailable?: Tool<INPUT, OUTPUT>['onInputAvailable'];
71
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
72
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
73
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
74
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
75
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
76
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
67
77
  },
68
- ) => Tool<INPUT, OUTPUT>;
78
+ ) => Tool<INPUT, OUTPUT, CONTEXT>;
69
79
 
70
80
  export function createProviderToolFactoryWithOutputSchema<
71
81
  INPUT,
72
82
  OUTPUT,
73
83
  ARGS extends object,
84
+ CONTEXT extends Context = {},
74
85
  >({
75
86
  id,
76
87
  inputSchema,
@@ -91,7 +102,7 @@ export function createProviderToolFactoryWithOutputSchema<
91
102
  * @default false
92
103
  */
93
104
  supportsDeferredResults?: boolean;
94
- }): ProviderToolFactoryWithOutputSchema<INPUT, OUTPUT, ARGS> {
105
+ }): ProviderToolFactoryWithOutputSchema<INPUT, OUTPUT, ARGS, CONTEXT> {
95
106
  return ({
96
107
  execute,
97
108
  needsApproval,
@@ -101,13 +112,13 @@ export function createProviderToolFactoryWithOutputSchema<
101
112
  onInputAvailable,
102
113
  ...args
103
114
  }: ARGS & {
104
- execute?: ToolExecuteFunction<INPUT, OUTPUT>;
105
- needsApproval?: Tool<INPUT, OUTPUT>['needsApproval'];
106
- toModelOutput?: Tool<INPUT, OUTPUT>['toModelOutput'];
107
- onInputStart?: Tool<INPUT, OUTPUT>['onInputStart'];
108
- onInputDelta?: Tool<INPUT, OUTPUT>['onInputDelta'];
109
- onInputAvailable?: Tool<INPUT, OUTPUT>['onInputAvailable'];
110
- }): Tool<INPUT, OUTPUT> =>
115
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
116
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
117
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
118
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
119
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
120
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
121
+ }): Tool<INPUT, OUTPUT, CONTEXT> =>
111
122
  tool({
112
123
  type: 'provider',
113
124
  id,
@@ -0,0 +1,27 @@
1
+ import {
2
+ NoSuchProviderReferenceError,
3
+ SharedV4ProviderReference,
4
+ } from '@ai-sdk/provider';
5
+
6
+ /**
7
+ * Resolves a provider reference to the provider-specific identifier for the
8
+ * given provider. Throws `NoSuchProviderReferenceError` if the provider is not
9
+ * found in the reference mapping.
10
+ */
11
+ export function resolveProviderReference({
12
+ reference,
13
+ provider,
14
+ }: {
15
+ reference: SharedV4ProviderReference;
16
+ provider: string;
17
+ }): string {
18
+ const id = reference[provider];
19
+ if (id != null) {
20
+ return id;
21
+ }
22
+
23
+ throw new NoSuchProviderReferenceError({
24
+ provider,
25
+ reference,
26
+ });
27
+ }
@@ -1,5 +1,7 @@
1
1
  import {
2
+ CustomPart,
2
3
  FilePart,
4
+ ReasoningFilePart,
3
5
  ReasoningPart,
4
6
  TextPart,
5
7
  ToolCallPart,
@@ -31,8 +33,10 @@ export type AssistantContent =
31
33
  | string
32
34
  | Array<
33
35
  | TextPart
36
+ | CustomPart
34
37
  | FilePart
35
38
  | ReasoningPart
39
+ | ReasoningFilePart
36
40
  | ToolCallPart
37
41
  | ToolResultPart
38
42
  | ToolApprovalRequest
@@ -1,6 +1,7 @@
1
1
  import { JSONValue } from '@ai-sdk/provider';
2
2
  import { DataContent } from './data-content';
3
3
  import { ProviderOptions } from './provider-options';
4
+ import { ProviderReference } from './provider-reference';
4
5
 
5
6
  /**
6
7
  * Text content part of a prompt. It contains a string of text.
@@ -32,8 +33,9 @@ export interface ImagePart {
32
33
  *
33
34
  * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer
34
35
  * - URL: a URL that points to the image
36
+ * - ProviderReference: a provider reference from `uploadFile`
35
37
  */
36
- image: DataContent | URL;
38
+ image: DataContent | URL | ProviderReference;
37
39
 
38
40
  /**
39
41
  * Optional IANA media type of the image.
@@ -60,9 +62,10 @@ export interface FilePart {
60
62
  * File data. Can either be:
61
63
  *
62
64
  * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer
63
- * - URL: a URL that points to the image
65
+ * - URL: a URL that points to the file
66
+ * - ProviderReference: a provider reference from `uploadFile`
64
67
  */
65
- data: DataContent | URL;
68
+ data: DataContent | URL | ProviderReference;
66
69
 
67
70
  /**
68
71
  * Optional filename of the file.
@@ -103,6 +106,55 @@ export interface ReasoningPart {
103
106
  providerOptions?: ProviderOptions;
104
107
  }
105
108
 
109
+ /**
110
+ * Custom content part of a prompt. It contains no standardized payload beyond
111
+ * provider-specific options.
112
+ */
113
+ export interface CustomPart {
114
+ type: 'custom';
115
+
116
+ /**
117
+ * The kind of custom content, in the format `{provider}.{provider-type}`.
118
+ */
119
+ kind: `${string}.${string}`;
120
+
121
+ /**
122
+ * Additional provider-specific metadata. They are passed through
123
+ * to the provider from the AI SDK and enable provider-specific
124
+ * functionality that can be fully encapsulated in the provider.
125
+ */
126
+ providerOptions?: ProviderOptions;
127
+ }
128
+
129
+ /**
130
+ * Reasoning file content part of a prompt. It contains a file generated as part of reasoning.
131
+ */
132
+ export interface ReasoningFilePart {
133
+ type: 'reasoning-file';
134
+
135
+ /**
136
+ * File data. Can either be:
137
+ *
138
+ * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer
139
+ * - URL: a URL that points to the file
140
+ */
141
+ data: DataContent | URL;
142
+
143
+ /**
144
+ * IANA media type of the file.
145
+ *
146
+ * @see https://www.iana.org/assignments/media-types/media-types.xhtml
147
+ */
148
+ mediaType: string;
149
+
150
+ /**
151
+ * Additional provider-specific metadata. They are passed through
152
+ * to the provider from the AI SDK and enable provider-specific
153
+ * functionality that can be fully encapsulated in the provider.
154
+ */
155
+ providerOptions?: ProviderOptions;
156
+ }
157
+
106
158
  /**
107
159
  * Tool call content part of a prompt. It contains a tool call (usually generated by the AI model).
108
160
  */
@@ -287,6 +339,9 @@ export type ToolResultOutput =
287
339
  providerOptions?: ProviderOptions;
288
340
  }
289
341
  | {
342
+ /**
343
+ * @deprecated Use file-reference instead.
344
+ */
290
345
  type: 'file-id';
291
346
 
292
347
  /**
@@ -299,6 +354,20 @@ export type ToolResultOutput =
299
354
  */
300
355
  fileId: string | Record<string, string>;
301
356
 
357
+ /**
358
+ * Provider-specific options.
359
+ */
360
+ providerOptions?: ProviderOptions;
361
+ }
362
+ | {
363
+ type: 'file-reference';
364
+
365
+ /**
366
+ * Provider-specific references for the file.
367
+ * The key is the provider name, e.g. 'openai' or 'anthropic'.
368
+ */
369
+ providerReference: ProviderReference;
370
+
302
371
  /**
303
372
  * Provider-specific options.
304
373
  */
@@ -344,7 +413,7 @@ export type ToolResultOutput =
344
413
  }
345
414
  | {
346
415
  /**
347
- * Images that are referenced using a provider file id.
416
+ * @deprecated Use image-file-reference instead.
348
417
  */
349
418
  type: 'image-file-id';
350
419
 
@@ -358,6 +427,23 @@ export type ToolResultOutput =
358
427
  */
359
428
  fileId: string | Record<string, string>;
360
429
 
430
+ /**
431
+ * Provider-specific options.
432
+ */
433
+ providerOptions?: ProviderOptions;
434
+ }
435
+ | {
436
+ /**
437
+ * Images that are referenced using a provider reference.
438
+ */
439
+ type: 'image-file-reference';
440
+
441
+ /**
442
+ * Provider-specific references for the image file.
443
+ * The key is the provider name, e.g. 'openai' or 'anthropic'.
444
+ */
445
+ providerReference: ProviderReference;
446
+
361
447
  /**
362
448
  * Provider-specific options.
363
449
  */
@@ -0,0 +1,4 @@
1
+ /**
2
+ * A context object that is passed into tool execution.
3
+ */
4
+ export type Context = Record<string, unknown>;
@@ -1,14 +1,34 @@
1
1
  import { isAsyncIterable } from '../is-async-iterable';
2
- import { ToolExecutionOptions, ToolExecuteFunction } from './tool';
2
+ import { Context } from './context';
3
+ import { ToolExecuteFunction, ToolExecutionOptions } from './tool';
3
4
 
4
- export async function* executeTool<INPUT, OUTPUT>({
5
+ /**
6
+ * Executes a tool function, supporting both synchronous and streaming/asynchronous results.
7
+ *
8
+ * This generator yields intermediate ("preliminary") outputs as they're produced, allowing callers
9
+ * to stream partial tool results before completion. When execution is finished, it yields a final output,
10
+ * ensuring all consumers receive a conclusive result.
11
+ *
12
+ * - If the tool's `execute` function returns an `AsyncIterable`, all intermediate values are yielded
13
+ * as `{ type: "preliminary", output }` except the last, which is yielded as `{ type: "final", output }`.
14
+ * - If the tool returns a direct value or Promise, a single `{ type: "final", output }` is yielded.
15
+ *
16
+ * @template INPUT Input type for the tool execution.
17
+ * @template OUTPUT Output type for the tool execution.
18
+ * @template CONTEXT Context object extension for execution (extends Context).
19
+ * @param params.execute The tool execute function.
20
+ * @param params.input Input value to pass to the execute function.
21
+ * @param params.options Additional options for tool execution.
22
+ * @yields An object containing either a preliminary or final output from the tool.
23
+ */
24
+ export async function* executeTool<INPUT, OUTPUT, CONTEXT extends Context>({
5
25
  execute,
6
26
  input,
7
27
  options,
8
28
  }: {
9
- execute: ToolExecuteFunction<INPUT, OUTPUT>;
29
+ execute: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
10
30
  input: INPUT;
11
- options: ToolExecutionOptions;
31
+ options: ToolExecutionOptions<NoInfer<CONTEXT>>;
12
32
  }): AsyncGenerator<
13
33
  { type: 'preliminary'; output: OUTPUT } | { type: 'final'; output: OUTPUT }
14
34
  > {