@ai-sdk/provider-utils 5.0.0-beta.3 → 5.0.0-beta.30

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 (110) hide show
  1. package/CHANGELOG.md +284 -0
  2. package/dist/index.d.ts +1339 -813
  3. package/dist/index.js +837 -288
  4. package/dist/index.js.map +1 -1
  5. package/dist/test/index.d.ts +2 -1
  6. package/dist/test/index.js +18 -37
  7. package/dist/test/index.js.map +1 -1
  8. package/package.json +13 -13
  9. package/src/add-additional-properties-to-json-schema.ts +1 -1
  10. package/src/as-array.ts +12 -0
  11. package/src/convert-image-model-file-to-data-uri.ts +3 -3
  12. package/src/convert-inline-file-data-to-uint8-array.ts +30 -0
  13. package/src/create-tool-name-mapping.ts +6 -22
  14. package/src/detect-media-type.ts +312 -0
  15. package/src/filter-nullable.ts +11 -0
  16. package/src/get-error-message.ts +1 -15
  17. package/src/get-from-api.ts +2 -2
  18. package/src/has-required-key.ts +6 -0
  19. package/src/index.ts +42 -12
  20. package/src/inject-json-instruction.ts +6 -6
  21. package/src/is-buffer.ts +9 -0
  22. package/src/is-json-serializable.ts +29 -0
  23. package/src/is-provider-reference.ts +21 -0
  24. package/src/is-url-supported.ts +17 -2
  25. package/src/load-api-key.ts +1 -1
  26. package/src/load-setting.ts +1 -1
  27. package/src/map-reasoning-to-provider.ts +108 -0
  28. package/src/maybe-promise-like.ts +3 -0
  29. package/src/parse-json-event-stream.ts +3 -3
  30. package/src/parse-json.ts +3 -3
  31. package/src/parse-provider-options.ts +1 -1
  32. package/src/post-to-api.ts +4 -4
  33. package/src/provider-defined-tool-factory.ts +129 -0
  34. package/src/provider-executed-tool-factory.ts +69 -0
  35. package/src/resolve-full-media-type.ts +49 -0
  36. package/src/resolve-provider-reference.ts +26 -0
  37. package/src/resolve.ts +16 -1
  38. package/src/response-handler.ts +3 -3
  39. package/src/schema.ts +6 -3
  40. package/src/secure-json-parse.ts +1 -1
  41. package/src/serialize-model-options.ts +63 -0
  42. package/src/streaming-tool-call-tracker.ts +241 -0
  43. package/src/test/convert-response-stream-to-array.ts +1 -1
  44. package/src/test/is-node-version.ts +22 -1
  45. package/src/to-json-schema/zod3-to-json-schema/options.ts +3 -3
  46. package/src/to-json-schema/zod3-to-json-schema/parse-def.ts +3 -3
  47. package/src/to-json-schema/zod3-to-json-schema/parse-types.ts +22 -22
  48. package/src/to-json-schema/zod3-to-json-schema/parsers/array.ts +3 -3
  49. package/src/to-json-schema/zod3-to-json-schema/parsers/bigint.ts +1 -1
  50. package/src/to-json-schema/zod3-to-json-schema/parsers/branded.ts +2 -2
  51. package/src/to-json-schema/zod3-to-json-schema/parsers/catch.ts +2 -2
  52. package/src/to-json-schema/zod3-to-json-schema/parsers/date.ts +4 -4
  53. package/src/to-json-schema/zod3-to-json-schema/parsers/default.ts +3 -3
  54. package/src/to-json-schema/zod3-to-json-schema/parsers/effects.ts +3 -3
  55. package/src/to-json-schema/zod3-to-json-schema/parsers/enum.ts +1 -1
  56. package/src/to-json-schema/zod3-to-json-schema/parsers/intersection.ts +5 -5
  57. package/src/to-json-schema/zod3-to-json-schema/parsers/literal.ts +1 -1
  58. package/src/to-json-schema/zod3-to-json-schema/parsers/map.ts +4 -5
  59. package/src/to-json-schema/zod3-to-json-schema/parsers/native-enum.ts +1 -1
  60. package/src/to-json-schema/zod3-to-json-schema/parsers/never.ts +1 -2
  61. package/src/to-json-schema/zod3-to-json-schema/parsers/nullable.ts +4 -4
  62. package/src/to-json-schema/zod3-to-json-schema/parsers/number.ts +1 -1
  63. package/src/to-json-schema/zod3-to-json-schema/parsers/object.ts +3 -3
  64. package/src/to-json-schema/zod3-to-json-schema/parsers/optional.ts +3 -3
  65. package/src/to-json-schema/zod3-to-json-schema/parsers/pipeline.ts +4 -4
  66. package/src/to-json-schema/zod3-to-json-schema/parsers/promise.ts +3 -3
  67. package/src/to-json-schema/zod3-to-json-schema/parsers/readonly.ts +2 -2
  68. package/src/to-json-schema/zod3-to-json-schema/parsers/record.ts +9 -10
  69. package/src/to-json-schema/zod3-to-json-schema/parsers/set.ts +3 -3
  70. package/src/to-json-schema/zod3-to-json-schema/parsers/string.ts +2 -2
  71. package/src/to-json-schema/zod3-to-json-schema/parsers/tuple.ts +3 -3
  72. package/src/to-json-schema/zod3-to-json-schema/parsers/undefined.ts +1 -2
  73. package/src/to-json-schema/zod3-to-json-schema/parsers/union.ts +3 -3
  74. package/src/to-json-schema/zod3-to-json-schema/parsers/unknown.ts +1 -2
  75. package/src/to-json-schema/zod3-to-json-schema/refs.ts +3 -3
  76. package/src/to-json-schema/zod3-to-json-schema/select-parser.ts +2 -2
  77. package/src/to-json-schema/zod3-to-json-schema/zod3-to-json-schema.ts +3 -3
  78. package/src/types/assistant-model-message.ts +5 -3
  79. package/src/types/content-part.ts +102 -24
  80. package/src/types/context.ts +4 -0
  81. package/src/types/executable-tool.ts +17 -0
  82. package/src/types/execute-tool.ts +29 -9
  83. package/src/types/file-data.ts +48 -0
  84. package/src/types/index.ts +26 -11
  85. package/src/types/infer-tool-context.ts +12 -0
  86. package/src/types/infer-tool-input.ts +7 -0
  87. package/src/types/infer-tool-output.ts +7 -0
  88. package/src/types/infer-tool-set-context.ts +15 -0
  89. package/src/types/model-message.ts +4 -4
  90. package/src/types/never-optional.ts +7 -0
  91. package/src/types/provider-options.ts +2 -2
  92. package/src/types/provider-reference.ts +10 -0
  93. package/src/types/sensitive-context.ts +9 -0
  94. package/src/types/system-model-message.ts +1 -1
  95. package/src/types/tool-approval-request.ts +7 -0
  96. package/src/types/tool-execute-function.ts +50 -0
  97. package/src/types/tool-model-message.ts +3 -3
  98. package/src/types/tool-needs-approval-function.ts +39 -0
  99. package/src/types/tool-set.ts +22 -0
  100. package/src/types/tool.ts +251 -222
  101. package/src/types/user-model-message.ts +2 -2
  102. package/src/validate-download-url.ts +7 -2
  103. package/src/validate-types.ts +5 -3
  104. package/dist/index.d.mts +0 -1458
  105. package/dist/index.mjs +0 -2759
  106. package/dist/index.mjs.map +0 -1
  107. package/dist/test/index.d.mts +0 -17
  108. package/dist/test/index.mjs +0 -77
  109. package/dist/test/index.mjs.map +0 -1
  110. package/src/provider-tool-factory.ts +0 -125
package/src/index.ts CHANGED
@@ -1,32 +1,45 @@
1
+ export { asArray } from './as-array';
2
+ export type { Arrayable } from './as-array';
1
3
  export * from './combine-headers';
2
4
  export { convertAsyncIteratorToReadableStream } from './convert-async-iterator-to-readable-stream';
5
+ export { convertInlineFileDataToUint8Array } from './convert-inline-file-data-to-uint8-array';
6
+ export { convertImageModelFileToDataUri } from './convert-image-model-file-to-data-uri';
7
+ export { convertToFormData } from './convert-to-form-data';
3
8
  export {
4
9
  createToolNameMapping,
5
10
  type ToolNameMapping,
6
11
  } from './create-tool-name-mapping';
7
12
  export * from './delay';
8
13
  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';
14
+ export {
15
+ detectMediaType,
16
+ getTopLevelMediaType,
17
+ isFullMediaType,
18
+ } from './detect-media-type';
12
19
  export { downloadBlob } from './download-blob';
13
20
  export { DownloadError } from './download-error';
14
- export {
15
- readResponseWithSizeLimit,
16
- DEFAULT_MAX_DOWNLOAD_SIZE,
17
- } from './read-response-with-size-limit';
21
+ export * from './extract-response-headers';
18
22
  export * from './fetch-function';
23
+ export { filterNullable } from './filter-nullable';
19
24
  export { createIdGenerator, generateId, type IdGenerator } from './generate-id';
20
25
  export * from './get-error-message';
21
26
  export * from './get-from-api';
22
27
  export { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-agent';
28
+ export type { HasRequiredKey } from './has-required-key';
23
29
  export { injectJsonInstructionIntoMessages } from './inject-json-instruction';
24
30
  export * from './is-abort-error';
31
+ export { isBuffer } from './is-buffer';
25
32
  export { isNonNullable } from './is-non-nullable';
33
+ export { isProviderReference } from './is-provider-reference';
26
34
  export { isUrlSupported } from './is-url-supported';
27
35
  export * from './load-api-key';
28
36
  export { loadOptionalSetting } from './load-optional-setting';
29
37
  export { loadSetting } from './load-setting';
38
+ export {
39
+ isCustomReasoning,
40
+ mapReasoningToProviderBudget,
41
+ mapReasoningToProviderEffort,
42
+ } from './map-reasoning-to-provider';
30
43
  export { type MaybePromiseLike } from './maybe-promise-like';
31
44
  export { mediaTypeToExtension } from './media-type-to-extension';
32
45
  export { normalizeHeaders } from './normalize-headers';
@@ -35,13 +48,23 @@ export { parseJsonEventStream } from './parse-json-event-stream';
35
48
  export { parseProviderOptions } from './parse-provider-options';
36
49
  export * from './post-to-api';
37
50
  export {
38
- createProviderToolFactory,
39
- createProviderToolFactoryWithOutputSchema,
40
- type ProviderToolFactory,
41
- type ProviderToolFactoryWithOutputSchema,
42
- } from './provider-tool-factory';
51
+ createProviderDefinedToolFactory,
52
+ createProviderDefinedToolFactoryWithOutputSchema,
53
+ type ProviderDefinedToolFactory,
54
+ type ProviderDefinedToolFactoryWithOutputSchema,
55
+ } from './provider-defined-tool-factory';
56
+ export {
57
+ createProviderExecutedToolFactory,
58
+ type ProviderExecutedToolFactory,
59
+ } from './provider-executed-tool-factory';
60
+ export {
61
+ DEFAULT_MAX_DOWNLOAD_SIZE,
62
+ readResponseWithSizeLimit,
63
+ } from './read-response-with-size-limit';
43
64
  export * from './remove-undefined-entries';
44
65
  export * from './resolve';
66
+ export { resolveFullMediaType } from './resolve-full-media-type';
67
+ export { resolveProviderReference } from './resolve-provider-reference';
45
68
  export * from './response-handler';
46
69
  export {
47
70
  asSchema,
@@ -54,6 +77,12 @@ export {
54
77
  type Schema,
55
78
  type ValidationResult,
56
79
  } from './schema';
80
+ export { serializeModelOptions } from './serialize-model-options';
81
+ export {
82
+ StreamingToolCallTracker,
83
+ type StreamingToolCallDelta,
84
+ type StreamingToolCallTrackerOptions,
85
+ } from './streaming-tool-call-tracker';
57
86
  export { stripFileExtension } from './strip-file-extension';
58
87
  export * from './uint8-utils';
59
88
  export { validateDownloadUrl } from './validate-download-url';
@@ -67,6 +96,7 @@ export * from './types';
67
96
 
68
97
  // external re-exports
69
98
  export type * from '@standard-schema/spec';
99
+ export { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE } from '@workflow/serde';
70
100
  export {
71
101
  EventSourceParserStream,
72
102
  type EventSourceMessage,
@@ -1,7 +1,7 @@
1
- import {
1
+ import type {
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,9 @@
1
+ /**
2
+ * Type-guard for Node.js `Buffer` instances.
3
+ *
4
+ * Uses optional chaining on `globalThis.Buffer` so it returns `false` in
5
+ * runtimes where `Buffer` is not available (e.g. CloudFlare Workers).
6
+ */
7
+ export function isBuffer(value: unknown): value is Buffer {
8
+ return globalThis.Buffer?.isBuffer(value) ?? false;
9
+ }
@@ -0,0 +1,29 @@
1
+ import type { 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,21 @@
1
+ import type { SharedV4ProviderReference } from '@ai-sdk/provider';
2
+ import { isBuffer } from './is-buffer';
3
+
4
+ /**
5
+ * Checks whether a value is a provider reference (a mapping of provider names
6
+ * to provider-specific identifiers) as opposed to raw bytes, a URL, or a
7
+ * tagged `{ type: ... }` object.
8
+ */
9
+ export function isProviderReference(
10
+ data: unknown,
11
+ ): data is SharedV4ProviderReference {
12
+ return (
13
+ typeof data === 'object' &&
14
+ data !== null &&
15
+ !(data instanceof Uint8Array) &&
16
+ !(data instanceof URL) &&
17
+ !(data instanceof ArrayBuffer) &&
18
+ !isBuffer(data) &&
19
+ !('type' in data)
20
+ );
21
+ }
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Checks if the given URL is supported natively by the model.
3
3
  *
4
- * @param mediaType - The media type of the URL. Case-sensitive.
4
+ * @param mediaType - The media type of the URL. Case-sensitive. May be a full
5
+ * `type/subtype`, a wildcard `type/*`, or just the
6
+ * top-level segment (e.g. `image`).
5
7
  * @param url - The URL to check.
6
8
  * @param supportedUrls - A record where keys are case-sensitive media types (or '*')
7
9
  * and values are arrays of RegExp patterns for URLs.
@@ -22,6 +24,8 @@ export function isUrlSupported({
22
24
  url = url.toLowerCase();
23
25
  mediaType = mediaType.toLowerCase();
24
26
 
27
+ const isTopLevelOnly = !mediaType.includes('/');
28
+
25
29
  return (
26
30
  Object.entries(supportedUrls)
27
31
  // standardize supported url map into lowercase prefixes:
@@ -32,7 +36,18 @@ export function isUrlSupported({
32
36
  : { mediaTypePrefix: mediaType.replace(/\*/, ''), regexes: value };
33
37
  })
34
38
  // gather all regexp pattern from matched media type prefixes:
35
- .filter(({ mediaTypePrefix }) => mediaType.startsWith(mediaTypePrefix))
39
+ .filter(({ mediaTypePrefix }) => {
40
+ if (mediaTypePrefix === '') {
41
+ return true;
42
+ }
43
+ // For a top-level-only media type (e.g. `image`), we cannot determine
44
+ // whether a specific subtype (e.g. `image/png`) would apply, so we
45
+ // only match the corresponding `type/*` prefix exactly.
46
+ if (isTopLevelOnly) {
47
+ return `${mediaType}/` === mediaTypePrefix;
48
+ }
49
+ return mediaType.startsWith(mediaTypePrefix);
50
+ })
36
51
  .flatMap(({ regexes }) => regexes)
37
52
  // check if any pattern matches the url:
38
53
  .some(pattern => pattern.test(url))
@@ -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,108 @@
1
+ import type {
2
+ LanguageModelV4CallOptions,
3
+ SharedV4Warning,
4
+ } from '@ai-sdk/provider';
5
+
6
+ export type ReasoningLevel = Exclude<
7
+ LanguageModelV4CallOptions['reasoning'],
8
+ 'none' | 'provider-default' | undefined
9
+ >;
10
+
11
+ export function isCustomReasoning(
12
+ reasoning: LanguageModelV4CallOptions['reasoning'],
13
+ ): reasoning is Exclude<
14
+ LanguageModelV4CallOptions['reasoning'],
15
+ 'provider-default' | undefined
16
+ > {
17
+ return reasoning !== undefined && reasoning !== 'provider-default';
18
+ }
19
+
20
+ /**
21
+ * Maps a top-level reasoning level to a provider-specific effort string using
22
+ * the given effort map. Pushes a compatibility warning if the reasoning level
23
+ * maps to a different string, or an unsupported warning if the level is not
24
+ * present in the map.
25
+ *
26
+ * @returns The mapped effort string, or `undefined` if the level is not
27
+ * supported.
28
+ */
29
+ export function mapReasoningToProviderEffort<T extends string>({
30
+ reasoning,
31
+ effortMap,
32
+ warnings,
33
+ }: {
34
+ reasoning: ReasoningLevel;
35
+ effortMap: Partial<Record<ReasoningLevel, T>>;
36
+ warnings: SharedV4Warning[];
37
+ }): T | undefined {
38
+ const mapped = effortMap[reasoning];
39
+
40
+ if (mapped == null) {
41
+ warnings.push({
42
+ type: 'unsupported',
43
+ feature: 'reasoning',
44
+ details: `reasoning "${reasoning}" is not supported by this model.`,
45
+ });
46
+ return undefined;
47
+ }
48
+
49
+ if (mapped !== reasoning) {
50
+ warnings.push({
51
+ type: 'compatibility',
52
+ feature: 'reasoning',
53
+ details: `reasoning "${reasoning}" is not directly supported by this model. mapped to effort "${mapped}".`,
54
+ });
55
+ }
56
+
57
+ return mapped;
58
+ }
59
+
60
+ const DEFAULT_REASONING_BUDGET_PERCENTAGES: Record<ReasoningLevel, number> = {
61
+ minimal: 0.02,
62
+ low: 0.1,
63
+ medium: 0.3,
64
+ high: 0.6,
65
+ xhigh: 0.9,
66
+ };
67
+
68
+ /**
69
+ * Maps a top-level reasoning level to an absolute token budget by multiplying
70
+ * the model's max output tokens by a percentage from the budget percentages
71
+ * map. The result is clamped between `minReasoningBudget` (default 1024) and
72
+ * `maxReasoningBudget`. Pushes an unsupported warning if the level is not
73
+ * present in the budget percentages map.
74
+ *
75
+ * @returns The computed token budget, or `undefined` if the level is not
76
+ * supported.
77
+ */
78
+ export function mapReasoningToProviderBudget({
79
+ reasoning,
80
+ maxOutputTokens,
81
+ maxReasoningBudget,
82
+ minReasoningBudget = 1024,
83
+ budgetPercentages = DEFAULT_REASONING_BUDGET_PERCENTAGES,
84
+ warnings,
85
+ }: {
86
+ reasoning: ReasoningLevel;
87
+ maxOutputTokens: number;
88
+ maxReasoningBudget: number;
89
+ minReasoningBudget?: number;
90
+ budgetPercentages?: Partial<Record<ReasoningLevel, number>>;
91
+ warnings: SharedV4Warning[];
92
+ }): number | undefined {
93
+ const pct = budgetPercentages[reasoning];
94
+
95
+ if (pct == null) {
96
+ warnings.push({
97
+ type: 'unsupported',
98
+ feature: 'reasoning',
99
+ details: `reasoning "${reasoning}" is not supported by this model.`,
100
+ });
101
+ return undefined;
102
+ }
103
+
104
+ return Math.min(
105
+ maxReasoningBudget,
106
+ Math.max(minReasoningBudget, Math.round(maxOutputTokens * pct)),
107
+ );
108
+ }
@@ -1,3 +1,6 @@
1
+ /**
2
+ * A value that can be provided either synchronously or as a promise-like.
3
+ */
1
4
  export type MaybePromiseLike<T> =
2
5
  | T // Raw value
3
6
  | PromiseLike<T>; // Promise of value
@@ -1,9 +1,9 @@
1
1
  import {
2
- EventSourceMessage,
3
2
  EventSourceParserStream,
3
+ type EventSourceMessage,
4
4
  } from 'eventsource-parser/stream';
5
- import { ParseResult, safeParseJSON } from './parse-json';
6
- import { FlexibleSchema } from './schema';
5
+ import { safeParseJSON, type ParseResult } from './parse-json';
6
+ import type { FlexibleSchema } from './schema';
7
7
 
8
8
  /**
9
9
  * Parses a JSON event stream into a stream of parsed JSON objects.
package/src/parse-json.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  JSONParseError,
3
- JSONValue,
4
3
  TypeValidationError,
4
+ type JSONValue,
5
5
  } from '@ai-sdk/provider';
6
6
  import { secureJsonParse } from './secure-json-parse';
7
7
  import { safeValidateTypes, validateTypes } from './validate-types';
8
- import { FlexibleSchema } from './schema';
8
+ import type { FlexibleSchema } from './schema';
9
9
 
10
10
  /**
11
11
  * Parses a JSON string into an unknown object.
@@ -43,7 +43,7 @@ export async function parseJSON<T>({
43
43
  return value;
44
44
  }
45
45
 
46
- return validateTypes<T>({ value, schema });
46
+ return await validateTypes<T>({ value, schema });
47
47
  } catch (error) {
48
48
  if (
49
49
  JSONParseError.isInstance(error) ||
@@ -1,6 +1,6 @@
1
1
  import { InvalidArgumentError } from '@ai-sdk/provider';
2
2
  import { safeValidateTypes } from './validate-types';
3
- import { FlexibleSchema } from './schema';
3
+ import type { FlexibleSchema } from './schema';
4
4
 
5
5
  export async function parseProviderOptions<OPTIONS>({
6
6
  provider,
@@ -1,9 +1,9 @@
1
1
  import { APICallError } from '@ai-sdk/provider';
2
2
  import { extractResponseHeaders } from './extract-response-headers';
3
- import { FetchFunction } from './fetch-function';
3
+ import type { FetchFunction } from './fetch-function';
4
4
  import { handleFetchError } from './handle-fetch-error';
5
5
  import { isAbortError } from './is-abort-error';
6
- import { ResponseHandler } from './response-handler';
6
+ import type { ResponseHandler } from './response-handler';
7
7
  import { getRuntimeEnvironmentUserAgent } from './get-runtime-environment-user-agent';
8
8
  import { withUserAgentSuffix } from './with-user-agent-suffix';
9
9
  import { VERSION } from './version';
@@ -28,7 +28,7 @@ export const postJsonToApi = async <T>({
28
28
  abortSignal?: AbortSignal;
29
29
  fetch?: FetchFunction;
30
30
  }) =>
31
- postToApi({
31
+ await postToApi({
32
32
  url,
33
33
  headers: {
34
34
  'Content-Type': 'application/json',
@@ -61,7 +61,7 @@ export const postFormDataToApi = async <T>({
61
61
  abortSignal?: AbortSignal;
62
62
  fetch?: FetchFunction;
63
63
  }) =>
64
- postToApi({
64
+ await postToApi({
65
65
  url,
66
66
  headers,
67
67
  body: {
@@ -0,0 +1,129 @@
1
+ import { tool, type ProviderDefinedTool, type Tool } from './types/tool';
2
+ import type { FlexibleSchema } from './schema';
3
+ import type { Context } from './types/context';
4
+ import type { ToolExecuteFunction } from './types/tool-execute-function';
5
+ /**
6
+ * A provider-defined tool is a tool for which the provider defines the input
7
+ * and output schemas, but does not execute the tool.
8
+ */
9
+ export type ProviderDefinedToolFactory<
10
+ INPUT,
11
+ ARGS extends object,
12
+ CONTEXT extends Context = {},
13
+ > = <OUTPUT>(
14
+ options: ARGS & {
15
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
16
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
17
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
18
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
19
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
20
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
21
+ },
22
+ ) => ProviderDefinedTool<INPUT, OUTPUT, CONTEXT>;
23
+
24
+ export function createProviderDefinedToolFactory<
25
+ INPUT,
26
+ ARGS extends object,
27
+ CONTEXT extends Context = {},
28
+ >({
29
+ id,
30
+ inputSchema,
31
+ }: {
32
+ id: `${string}.${string}`;
33
+ inputSchema: FlexibleSchema<INPUT>;
34
+ }): ProviderDefinedToolFactory<INPUT, ARGS, CONTEXT> {
35
+ return <OUTPUT>({
36
+ execute,
37
+ outputSchema,
38
+ needsApproval,
39
+ toModelOutput,
40
+ onInputStart,
41
+ onInputDelta,
42
+ onInputAvailable,
43
+ ...args
44
+ }: ARGS & {
45
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
46
+ outputSchema?: FlexibleSchema<OUTPUT>;
47
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
48
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
49
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
50
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
51
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
52
+ }): ProviderDefinedTool<INPUT, OUTPUT, CONTEXT> =>
53
+ tool({
54
+ type: 'provider',
55
+ isProviderExecuted: false,
56
+ id,
57
+ args,
58
+ inputSchema,
59
+ outputSchema,
60
+ execute,
61
+ needsApproval,
62
+ toModelOutput,
63
+ onInputStart,
64
+ onInputDelta,
65
+ onInputAvailable,
66
+ }) as ProviderDefinedTool<INPUT, OUTPUT, CONTEXT>;
67
+ }
68
+
69
+ export type ProviderDefinedToolFactoryWithOutputSchema<
70
+ INPUT,
71
+ OUTPUT,
72
+ ARGS extends object,
73
+ CONTEXT extends Context = {},
74
+ > = (
75
+ options: ARGS & {
76
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
77
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
78
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
79
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
80
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
81
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
82
+ },
83
+ ) => ProviderDefinedTool<INPUT, OUTPUT, CONTEXT>;
84
+
85
+ export function createProviderDefinedToolFactoryWithOutputSchema<
86
+ INPUT,
87
+ OUTPUT,
88
+ ARGS extends object,
89
+ CONTEXT extends Context = {},
90
+ >({
91
+ id,
92
+ inputSchema,
93
+ outputSchema,
94
+ }: {
95
+ id: `${string}.${string}`;
96
+ inputSchema: FlexibleSchema<INPUT>;
97
+ outputSchema: FlexibleSchema<OUTPUT>;
98
+ }): ProviderDefinedToolFactoryWithOutputSchema<INPUT, OUTPUT, ARGS, CONTEXT> {
99
+ return ({
100
+ execute,
101
+ needsApproval,
102
+ toModelOutput,
103
+ onInputStart,
104
+ onInputDelta,
105
+ onInputAvailable,
106
+ ...args
107
+ }: ARGS & {
108
+ execute?: ToolExecuteFunction<INPUT, OUTPUT, CONTEXT>;
109
+ needsApproval?: Tool<INPUT, OUTPUT, CONTEXT>['needsApproval'];
110
+ toModelOutput?: Tool<INPUT, OUTPUT, CONTEXT>['toModelOutput'];
111
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
112
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
113
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
114
+ }): ProviderDefinedTool<INPUT, OUTPUT, CONTEXT> =>
115
+ tool({
116
+ type: 'provider',
117
+ isProviderExecuted: false,
118
+ id,
119
+ args,
120
+ inputSchema,
121
+ outputSchema,
122
+ execute,
123
+ needsApproval,
124
+ toModelOutput,
125
+ onInputStart,
126
+ onInputDelta,
127
+ onInputAvailable,
128
+ }) as ProviderDefinedTool<INPUT, OUTPUT, CONTEXT>;
129
+ }
@@ -0,0 +1,69 @@
1
+ import type { FlexibleSchema } from './schema';
2
+ import type { Context } from './types/context';
3
+ import { tool, type ProviderExecutedTool, type Tool } from './types/tool';
4
+ /**
5
+ * A provider-executed tool is a tool for which the provider executes the tool.
6
+ */
7
+ export type ProviderExecutedToolFactory<
8
+ INPUT,
9
+ OUTPUT,
10
+ ARGS extends object,
11
+ CONTEXT extends Context = {},
12
+ > = (
13
+ options: ARGS & {
14
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
15
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
16
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
17
+ },
18
+ ) => ProviderExecutedTool<INPUT, OUTPUT, CONTEXT>;
19
+
20
+ export function createProviderExecutedToolFactory<
21
+ INPUT,
22
+ OUTPUT,
23
+ ARGS extends object,
24
+ CONTEXT extends Context = {},
25
+ >({
26
+ id,
27
+ inputSchema,
28
+ outputSchema,
29
+ supportsDeferredResults,
30
+ }: {
31
+ id: `${string}.${string}`;
32
+ inputSchema: FlexibleSchema<INPUT>;
33
+ outputSchema: FlexibleSchema<OUTPUT>;
34
+
35
+ /**
36
+ * Whether this provider-executed tool supports deferred results.
37
+ *
38
+ * When true, the tool result may not be returned in the same turn as the
39
+ * tool call (e.g., when using programmatic tool calling where a server tool
40
+ * triggers a client-executed tool, and the server tool's result is deferred
41
+ * until the client tool is resolved).
42
+ *
43
+ * @default false
44
+ */
45
+ supportsDeferredResults?: boolean;
46
+ }): ProviderExecutedToolFactory<INPUT, OUTPUT, ARGS, CONTEXT> {
47
+ return ({
48
+ onInputStart,
49
+ onInputDelta,
50
+ onInputAvailable,
51
+ ...args
52
+ }: ARGS & {
53
+ onInputStart?: Tool<INPUT, OUTPUT, CONTEXT>['onInputStart'];
54
+ onInputDelta?: Tool<INPUT, OUTPUT, CONTEXT>['onInputDelta'];
55
+ onInputAvailable?: Tool<INPUT, OUTPUT, CONTEXT>['onInputAvailable'];
56
+ }): ProviderExecutedTool<INPUT, OUTPUT, CONTEXT> =>
57
+ tool({
58
+ type: 'provider',
59
+ isProviderExecuted: true,
60
+ id,
61
+ args,
62
+ inputSchema,
63
+ outputSchema,
64
+ onInputStart,
65
+ onInputDelta,
66
+ onInputAvailable,
67
+ supportsDeferredResults,
68
+ }) as ProviderExecutedTool<INPUT, OUTPUT, CONTEXT>;
69
+ }