@ai-sdk/provider-utils 5.0.0-beta.2 → 5.0.0-beta.21

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +226 -0
  2. package/dist/index.d.ts +433 -174
  3. package/dist/index.js +322 -284
  4. package/dist/index.js.map +1 -1
  5. package/dist/test/index.js +2 -35
  6. package/dist/test/index.js.map +1 -1
  7. package/package.json +8 -10
  8. package/src/convert-image-model-file-to-data-uri.ts +3 -3
  9. package/src/create-tool-name-mapping.ts +5 -21
  10. package/src/get-error-message.ts +1 -15
  11. package/src/has-required-key.ts +6 -0
  12. package/src/index.ts +17 -7
  13. package/src/inject-json-instruction.ts +5 -5
  14. package/src/is-json-serializable.ts +29 -0
  15. package/src/is-provider-reference.ts +18 -0
  16. package/src/load-api-key.ts +1 -1
  17. package/src/load-setting.ts +1 -1
  18. package/src/map-reasoning-to-provider.ts +105 -0
  19. package/src/provider-tool-factory.ts +43 -32
  20. package/src/resolve-provider-reference.ts +27 -0
  21. package/src/resolve.ts +15 -0
  22. package/src/response-handler.ts +1 -1
  23. package/src/secure-json-parse.ts +1 -1
  24. package/src/serialize-model-options.ts +63 -0
  25. package/src/to-json-schema/zod3-to-json-schema/parsers/date.ts +1 -1
  26. package/src/to-json-schema/zod3-to-json-schema/parsers/intersection.ts +1 -1
  27. package/src/to-json-schema/zod3-to-json-schema/parsers/record.ts +2 -2
  28. package/src/types/assistant-model-message.ts +4 -0
  29. package/src/types/content-part.ts +98 -14
  30. package/src/types/context.ts +4 -0
  31. package/src/types/executable-tool.ts +17 -0
  32. package/src/types/execute-tool.ts +28 -9
  33. package/src/types/index.ts +11 -9
  34. package/src/types/infer-tool-context.ts +12 -0
  35. package/src/types/infer-tool-input.ts +7 -0
  36. package/src/types/infer-tool-output.ts +7 -0
  37. package/src/types/infer-tool-set-context.ts +17 -0
  38. package/src/types/provider-options.ts +2 -2
  39. package/src/types/provider-reference.ts +10 -0
  40. package/src/types/tool-set.ts +22 -0
  41. package/src/types/tool.ts +74 -40
  42. package/src/types/union-to-intersection.ts +17 -0
  43. package/src/validate-download-url.ts +7 -2
  44. package/dist/index.d.mts +0 -1433
  45. package/dist/index.mjs +0 -2759
  46. package/dist/index.mjs.map +0 -1
  47. package/dist/test/index.d.mts +0 -17
  48. package/dist/test/index.mjs +0 -77
  49. package/dist/test/index.mjs.map +0 -1
@@ -1,35 +1,3 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/test/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- convertArrayToAsyncIterable: () => convertArrayToAsyncIterable,
24
- convertArrayToReadableStream: () => convertArrayToReadableStream,
25
- convertAsyncIterableToArray: () => convertAsyncIterableToArray,
26
- convertReadableStreamToArray: () => convertReadableStreamToArray,
27
- convertResponseStreamToArray: () => convertResponseStreamToArray,
28
- isNodeVersion: () => isNodeVersion,
29
- mockId: () => mockId
30
- });
31
- module.exports = __toCommonJS(index_exports);
32
-
33
1
  // src/test/convert-array-to-async-iterable.ts
34
2
  function convertArrayToAsyncIterable(values) {
35
3
  return {
@@ -97,8 +65,7 @@ function mockId({
97
65
  let counter = 0;
98
66
  return () => `${prefix}-${counter++}`;
99
67
  }
100
- // Annotate the CommonJS export names for ESM import in node:
101
- 0 && (module.exports = {
68
+ export {
102
69
  convertArrayToAsyncIterable,
103
70
  convertArrayToReadableStream,
104
71
  convertAsyncIterableToArray,
@@ -106,5 +73,5 @@ function mockId({
106
73
  convertResponseStreamToArray,
107
74
  isNodeVersion,
108
75
  mockId
109
- });
76
+ };
110
77
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/test/index.ts","../../src/test/convert-array-to-async-iterable.ts","../../src/test/convert-array-to-readable-stream.ts","../../src/test/convert-async-iterable-to-array.ts","../../src/test/convert-readable-stream-to-array.ts","../../src/test/convert-response-stream-to-array.ts","../../src/test/is-node-version.ts","../../src/test/mock-id.ts"],"sourcesContent":["export * from './convert-array-to-async-iterable';\nexport * from './convert-array-to-readable-stream';\nexport * from './convert-async-iterable-to-array';\nexport * from './convert-readable-stream-to-array';\nexport * from './convert-response-stream-to-array';\nexport * from './is-node-version';\nexport * from './mock-id';\n","export function convertArrayToAsyncIterable<T>(values: T[]): AsyncIterable<T> {\n return {\n async *[Symbol.asyncIterator]() {\n for (const value of values) {\n yield value;\n }\n },\n };\n}\n","export function convertArrayToReadableStream<T>(\n values: T[],\n): ReadableStream<T> {\n return new ReadableStream({\n start(controller) {\n try {\n for (const value of values) {\n controller.enqueue(value);\n }\n } finally {\n controller.close();\n }\n },\n });\n}\n","export async function convertAsyncIterableToArray<T>(\n iterable: AsyncIterable<T>,\n): Promise<T[]> {\n const result: T[] = [];\n for await (const item of iterable) {\n result.push(item);\n }\n return result;\n}\n","export async function convertReadableStreamToArray<T>(\n stream: ReadableStream<T>,\n): Promise<T[]> {\n const reader = stream.getReader();\n const result: T[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n result.push(value);\n }\n\n return result;\n}\n","import { convertReadableStreamToArray } from './convert-readable-stream-to-array';\n\nexport async function convertResponseStreamToArray(\n response: Response,\n): Promise<string[]> {\n return convertReadableStreamToArray(\n response.body!.pipeThrough(new TextDecoderStream()),\n );\n}\n","export function isNodeVersion(version: number) {\n const nodeMajorVersion = parseInt(process.version.slice(1).split('.')[0], 10);\n return nodeMajorVersion === version;\n}\n","export function mockId({\n prefix = 'id',\n}: {\n prefix?: string;\n} = {}): () => string {\n let counter = 0;\n return () => `${prefix}-${counter++}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,4BAA+B,QAA+B;AAC5E,SAAO;AAAA,IACL,QAAQ,OAAO,aAAa,IAAI;AAC9B,iBAAW,SAAS,QAAQ;AAC1B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;;;ACRO,SAAS,6BACd,QACmB;AACnB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,YAAY;AAChB,UAAI;AACF,mBAAW,SAAS,QAAQ;AAC1B,qBAAW,QAAQ,KAAK;AAAA,QAC1B;AAAA,MACF,UAAE;AACA,mBAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;ACdA,eAAsB,4BACpB,UACc;AACd,QAAM,SAAc,CAAC;AACrB,mBAAiB,QAAQ,UAAU;AACjC,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO;AACT;;;ACRA,eAAsB,6BACpB,QACc;AACd,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,SAAc,CAAC;AAErB,SAAO,MAAM;AACX,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AACV,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO;AACT;;;ACXA,eAAsB,6BACpB,UACmB;AACnB,SAAO;AAAA,IACL,SAAS,KAAM,YAAY,IAAI,kBAAkB,CAAC;AAAA,EACpD;AACF;;;ACRO,SAAS,cAAc,SAAiB;AAC7C,QAAM,mBAAmB,SAAS,QAAQ,QAAQ,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE;AAC5E,SAAO,qBAAqB;AAC9B;;;ACHO,SAAS,OAAO;AAAA,EACrB,SAAS;AACX,IAEI,CAAC,GAAiB;AACpB,MAAI,UAAU;AACd,SAAO,MAAM,GAAG,MAAM,IAAI,SAAS;AACrC;","names":[]}
1
+ {"version":3,"sources":["../../src/test/convert-array-to-async-iterable.ts","../../src/test/convert-array-to-readable-stream.ts","../../src/test/convert-async-iterable-to-array.ts","../../src/test/convert-readable-stream-to-array.ts","../../src/test/convert-response-stream-to-array.ts","../../src/test/is-node-version.ts","../../src/test/mock-id.ts"],"sourcesContent":["export function convertArrayToAsyncIterable<T>(values: T[]): AsyncIterable<T> {\n return {\n async *[Symbol.asyncIterator]() {\n for (const value of values) {\n yield value;\n }\n },\n };\n}\n","export function convertArrayToReadableStream<T>(\n values: T[],\n): ReadableStream<T> {\n return new ReadableStream({\n start(controller) {\n try {\n for (const value of values) {\n controller.enqueue(value);\n }\n } finally {\n controller.close();\n }\n },\n });\n}\n","export async function convertAsyncIterableToArray<T>(\n iterable: AsyncIterable<T>,\n): Promise<T[]> {\n const result: T[] = [];\n for await (const item of iterable) {\n result.push(item);\n }\n return result;\n}\n","export async function convertReadableStreamToArray<T>(\n stream: ReadableStream<T>,\n): Promise<T[]> {\n const reader = stream.getReader();\n const result: T[] = [];\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n result.push(value);\n }\n\n return result;\n}\n","import { convertReadableStreamToArray } from './convert-readable-stream-to-array';\n\nexport async function convertResponseStreamToArray(\n response: Response,\n): Promise<string[]> {\n return convertReadableStreamToArray(\n response.body!.pipeThrough(new TextDecoderStream()),\n );\n}\n","export function isNodeVersion(version: number) {\n const nodeMajorVersion = parseInt(process.version.slice(1).split('.')[0], 10);\n return nodeMajorVersion === version;\n}\n","export function mockId({\n prefix = 'id',\n}: {\n prefix?: string;\n} = {}): () => string {\n let counter = 0;\n return () => `${prefix}-${counter++}`;\n}\n"],"mappings":";AAAO,SAAS,4BAA+B,QAA+B;AAC5E,SAAO;AAAA,IACL,QAAQ,OAAO,aAAa,IAAI;AAC9B,iBAAW,SAAS,QAAQ;AAC1B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;;;ACRO,SAAS,6BACd,QACmB;AACnB,SAAO,IAAI,eAAe;AAAA,IACxB,MAAM,YAAY;AAChB,UAAI;AACF,mBAAW,SAAS,QAAQ;AAC1B,qBAAW,QAAQ,KAAK;AAAA,QAC1B;AAAA,MACF,UAAE;AACA,mBAAW,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,EACF,CAAC;AACH;;;ACdA,eAAsB,4BACpB,UACc;AACd,QAAM,SAAc,CAAC;AACrB,mBAAiB,QAAQ,UAAU;AACjC,WAAO,KAAK,IAAI;AAAA,EAClB;AACA,SAAO;AACT;;;ACRA,eAAsB,6BACpB,QACc;AACd,QAAM,SAAS,OAAO,UAAU;AAChC,QAAM,SAAc,CAAC;AAErB,SAAO,MAAM;AACX,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,KAAM;AACV,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO;AACT;;;ACXA,eAAsB,6BACpB,UACmB;AACnB,SAAO;AAAA,IACL,SAAS,KAAM,YAAY,IAAI,kBAAkB,CAAC;AAAA,EACpD;AACF;;;ACRO,SAAS,cAAc,SAAiB;AAC7C,QAAM,mBAAmB,SAAS,QAAQ,QAAQ,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE;AAC5E,SAAO,qBAAqB;AAC9B;;;ACHO,SAAS,OAAO;AAAA,EACrB,SAAS;AACX,IAEI,CAAC,GAAiB;AACpB,MAAI,UAAU;AACd,SAAO,MAAM,GAAG,MAAM,IAAI,SAAS;AACrC;","names":[]}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@ai-sdk/provider-utils",
3
- "version": "5.0.0-beta.2",
3
+ "version": "5.0.0-beta.21",
4
+ "type": "module",
4
5
  "license": "Apache-2.0",
5
6
  "sideEffects": false,
6
7
  "main": "./dist/index.js",
7
- "module": "./dist/index.mjs",
8
8
  "types": "./dist/index.d.ts",
9
9
  "source": "./src/index.ts",
10
10
  "files": [
@@ -22,20 +22,20 @@
22
22
  "./package.json": "./package.json",
23
23
  ".": {
24
24
  "types": "./dist/index.d.ts",
25
- "import": "./dist/index.mjs",
26
- "require": "./dist/index.js"
25
+ "import": "./dist/index.js",
26
+ "default": "./dist/index.js"
27
27
  },
28
28
  "./test": {
29
29
  "types": "./dist/test/index.d.ts",
30
- "import": "./dist/test/index.mjs",
31
- "module": "./dist/test/index.mjs",
32
- "require": "./dist/test/index.js"
30
+ "import": "./dist/test/index.js",
31
+ "default": "./dist/test/index.js"
33
32
  }
34
33
  },
35
34
  "dependencies": {
36
35
  "@standard-schema/spec": "^1.1.0",
36
+ "@workflow/serde": "4.1.0",
37
37
  "eventsource-parser": "^3.0.6",
38
- "@ai-sdk/provider": "4.0.0-beta.1"
38
+ "@ai-sdk/provider": "4.0.0-beta.12"
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
  }
@@ -1,15 +1 @@
1
- export function getErrorMessage(error: unknown | undefined) {
2
- if (error == null) {
3
- return 'unknown error';
4
- }
5
-
6
- if (typeof error === 'string') {
7
- return error;
8
- }
9
-
10
- if (error instanceof Error) {
11
- return error.message;
12
- }
13
-
14
- return JSON.stringify(error);
15
- }
1
+ export { getErrorMessage } from '@ai-sdk/provider';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Checks if an object has required keys.
3
+ * @param OBJECT - The object to check.
4
+ * @returns True if the object has required keys, false otherwise.
5
+ */
6
+ export type HasRequiredKey<OBJECT> = {} extends OBJECT ? false : true;
package/src/index.ts CHANGED
@@ -1,32 +1,35 @@
1
1
  export * from './combine-headers';
2
2
  export { convertAsyncIteratorToReadableStream } from './convert-async-iterator-to-readable-stream';
3
+ export { convertImageModelFileToDataUri } from './convert-image-model-file-to-data-uri';
4
+ export { convertToFormData } from './convert-to-form-data';
3
5
  export {
4
6
  createToolNameMapping,
5
7
  type ToolNameMapping,
6
8
  } from './create-tool-name-mapping';
7
9
  export * from './delay';
8
10
  export { DelayedPromise } from './delayed-promise';
9
- export * from './extract-response-headers';
10
- export { convertImageModelFileToDataUri } from './convert-image-model-file-to-data-uri';
11
- export { convertToFormData } from './convert-to-form-data';
12
11
  export { downloadBlob } from './download-blob';
13
12
  export { DownloadError } from './download-error';
14
- export {
15
- readResponseWithSizeLimit,
16
- DEFAULT_MAX_DOWNLOAD_SIZE,
17
- } from './read-response-with-size-limit';
13
+ export * from './extract-response-headers';
18
14
  export * from './fetch-function';
19
15
  export { createIdGenerator, generateId, type IdGenerator } from './generate-id';
20
16
  export * from './get-error-message';
21
17
  export * from './get-from-api';
22
18
  export { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-agent';
19
+ export type { HasRequiredKey } from './has-required-key';
23
20
  export { injectJsonInstructionIntoMessages } from './inject-json-instruction';
24
21
  export * from './is-abort-error';
25
22
  export { isNonNullable } from './is-non-nullable';
23
+ export { isProviderReference } from './is-provider-reference';
26
24
  export { isUrlSupported } from './is-url-supported';
27
25
  export * from './load-api-key';
28
26
  export { loadOptionalSetting } from './load-optional-setting';
29
27
  export { loadSetting } from './load-setting';
28
+ export {
29
+ isCustomReasoning,
30
+ mapReasoningToProviderBudget,
31
+ mapReasoningToProviderEffort,
32
+ } from './map-reasoning-to-provider';
30
33
  export { type MaybePromiseLike } from './maybe-promise-like';
31
34
  export { mediaTypeToExtension } from './media-type-to-extension';
32
35
  export { normalizeHeaders } from './normalize-headers';
@@ -40,8 +43,13 @@ export {
40
43
  type ProviderToolFactory,
41
44
  type ProviderToolFactoryWithOutputSchema,
42
45
  } from './provider-tool-factory';
46
+ export {
47
+ DEFAULT_MAX_DOWNLOAD_SIZE,
48
+ readResponseWithSizeLimit,
49
+ } from './read-response-with-size-limit';
43
50
  export * from './remove-undefined-entries';
44
51
  export * from './resolve';
52
+ export { resolveProviderReference } from './resolve-provider-reference';
45
53
  export * from './response-handler';
46
54
  export {
47
55
  asSchema,
@@ -54,6 +62,7 @@ export {
54
62
  type Schema,
55
63
  type ValidationResult,
56
64
  } from './schema';
65
+ export { serializeModelOptions } from './serialize-model-options';
57
66
  export { stripFileExtension } from './strip-file-extension';
58
67
  export * from './uint8-utils';
59
68
  export { validateDownloadUrl } from './validate-download-url';
@@ -67,6 +76,7 @@ export * from './types';
67
76
 
68
77
  // external re-exports
69
78
  export type * from '@standard-schema/spec';
79
+ export { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from '@workflow/serde';
70
80
  export {
71
81
  EventSourceParserStream,
72
82
  type EventSourceMessage,
@@ -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,29 @@
1
+ import { JSONValue } from '@ai-sdk/provider';
2
+
3
+ /**
4
+ * Checks whether a value can cross a workflow serialization boundary.
5
+ *
6
+ * The check accepts JSON-like primitives, arrays, and plain objects whose
7
+ * nested values are also serializable. It rejects functions, symbols,
8
+ * bigints, and non-plain objects such as class instances, dates, and regexes.
9
+ */
10
+ export function isJSONSerializable(value: unknown): value is JSONValue {
11
+ if (value === null || value === undefined) return true;
12
+
13
+ const type = typeof value;
14
+ if (type === 'string' || type === 'number' || type === 'boolean') return true;
15
+ if (type === 'function' || type === 'symbol' || type === 'bigint')
16
+ return false;
17
+
18
+ if (Array.isArray(value)) {
19
+ return value.every(isJSONSerializable);
20
+ }
21
+
22
+ if (Object.getPrototypeOf(value) === Object.prototype) {
23
+ return Object.values(value as Record<string, unknown>).every(
24
+ isJSONSerializable,
25
+ );
26
+ }
27
+
28
+ return false;
29
+ }
@@ -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
+ }
@@ -23,7 +23,7 @@ export function loadApiKey({
23
23
 
24
24
  if (typeof process === 'undefined') {
25
25
  throw new LoadAPIKeyError({
26
- message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter. Environment variables is not supported in this environment.`,
26
+ message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter. Environment variables are not supported in this environment.`,
27
27
  });
28
28
  }
29
29
 
@@ -35,7 +35,7 @@ export function loadSetting({
35
35
  message:
36
36
  `${description} setting is missing. ` +
37
37
  `Pass it using the '${settingName}' parameter. ` +
38
- `Environment variables is not supported in this environment.`,
38
+ `Environment variables are not supported in this environment.`,
39
39
  });
40
40
  }
41
41
 
@@ -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
+ }
package/src/resolve.ts CHANGED
@@ -1,5 +1,20 @@
1
1
  import { MaybePromiseLike } from './maybe-promise-like';
2
2
 
3
+ /**
4
+ * A value or a lazy provider of a value, each of which may be synchronous or asynchronous.
5
+ *
6
+ * @template T The resolved type after {@link resolve} runs.
7
+ *
8
+ * One of:
9
+ * - A plain value of type {@link T}
10
+ * - A {@link PromiseLike} of {@link T} (e.g. a `Promise<T>`)
11
+ * - A zero-argument function that returns a plain {@link T}
12
+ * - A zero-argument function that returns a {@link PromiseLike} of {@link T}
13
+ *
14
+ * The function form is only invoked when passed to {@link resolve}; it is not distinguished from
15
+ * a {@link T} that happens to be a function—callers should wrap function values if disambiguation
16
+ * is required.
17
+ */
3
18
  export type Resolvable<T> = MaybePromiseLike<T> | (() => MaybePromiseLike<T>);
4
19
 
5
20
  /**