@ai-sdk/provider-utils 4.0.8 → 4.0.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/index.js +29 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +29 -1
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +6 -2
  7. package/src/handle-fetch-error.ts +33 -0
  8. package/src/__snapshots__/schema.test.ts.snap +0 -346
  9. package/src/add-additional-properties-to-json-schema.test.ts +0 -289
  10. package/src/convert-async-iterator-to-readable-stream.test.ts +0 -78
  11. package/src/convert-image-model-file-to-data-uri.test.ts +0 -85
  12. package/src/convert-to-form-data.test.ts +0 -167
  13. package/src/create-tool-name-mapping.test.ts +0 -163
  14. package/src/delay.test.ts +0 -212
  15. package/src/delayed-promise.test.ts +0 -132
  16. package/src/download-blob.test.ts +0 -145
  17. package/src/generate-id.test.ts +0 -31
  18. package/src/get-from-api.test.ts +0 -199
  19. package/src/get-runtime-environment-user-agent.test.ts +0 -47
  20. package/src/inject-json-instruction.test.ts +0 -404
  21. package/src/is-url-supported.test.ts +0 -282
  22. package/src/media-type-to-extension.test.ts +0 -26
  23. package/src/normalize-headers.test.ts +0 -64
  24. package/src/parse-json.test.ts +0 -191
  25. package/src/remove-undefined-entries.test.ts +0 -57
  26. package/src/resolve.test.ts +0 -125
  27. package/src/response-handler.test.ts +0 -89
  28. package/src/schema.test-d.ts +0 -11
  29. package/src/schema.test.ts +0 -502
  30. package/src/secure-json-parse.test.ts +0 -59
  31. package/src/to-json-schema/zod3-to-json-schema/parse-def.test.ts +0 -224
  32. package/src/to-json-schema/zod3-to-json-schema/parsers/array.test.ts +0 -98
  33. package/src/to-json-schema/zod3-to-json-schema/parsers/bigint.test.ts +0 -51
  34. package/src/to-json-schema/zod3-to-json-schema/parsers/branded.test.ts +0 -16
  35. package/src/to-json-schema/zod3-to-json-schema/parsers/catch.test.ts +0 -15
  36. package/src/to-json-schema/zod3-to-json-schema/parsers/date.test.ts +0 -97
  37. package/src/to-json-schema/zod3-to-json-schema/parsers/default.test.ts +0 -54
  38. package/src/to-json-schema/zod3-to-json-schema/parsers/effects.test.ts +0 -41
  39. package/src/to-json-schema/zod3-to-json-schema/parsers/intersection.test.ts +0 -92
  40. package/src/to-json-schema/zod3-to-json-schema/parsers/map.test.ts +0 -48
  41. package/src/to-json-schema/zod3-to-json-schema/parsers/native-enum.test.ts +0 -102
  42. package/src/to-json-schema/zod3-to-json-schema/parsers/nullable.test.ts +0 -67
  43. package/src/to-json-schema/zod3-to-json-schema/parsers/number.test.ts +0 -65
  44. package/src/to-json-schema/zod3-to-json-schema/parsers/object.test.ts +0 -149
  45. package/src/to-json-schema/zod3-to-json-schema/parsers/optional.test.ts +0 -147
  46. package/src/to-json-schema/zod3-to-json-schema/parsers/pipe.test.ts +0 -35
  47. package/src/to-json-schema/zod3-to-json-schema/parsers/promise.test.ts +0 -15
  48. package/src/to-json-schema/zod3-to-json-schema/parsers/readonly.test.ts +0 -20
  49. package/src/to-json-schema/zod3-to-json-schema/parsers/record.test.ts +0 -108
  50. package/src/to-json-schema/zod3-to-json-schema/parsers/set.test.ts +0 -20
  51. package/src/to-json-schema/zod3-to-json-schema/parsers/string.test.ts +0 -438
  52. package/src/to-json-schema/zod3-to-json-schema/parsers/tuple.test.ts +0 -33
  53. package/src/to-json-schema/zod3-to-json-schema/parsers/union.test.ts +0 -226
  54. package/src/to-json-schema/zod3-to-json-schema/refs.test.ts +0 -919
  55. package/src/to-json-schema/zod3-to-json-schema/zod3-to-json-schema.test.ts +0 -862
  56. package/src/types/tool.test-d.ts +0 -228
  57. package/src/validate-types.test.ts +0 -105
  58. package/src/with-user-agent-suffix.test.ts +0 -84
@@ -1,228 +0,0 @@
1
- import { LanguageModelV3ToolResultPart } from '@ai-sdk/provider';
2
- import { describe, expectTypeOf, it } from 'vitest';
3
- import { z } from 'zod/v4';
4
- import { FlexibleSchema } from '../schema';
5
- import { ModelMessage } from './model-message';
6
- import { Tool, tool, ToolExecuteFunction } from './tool';
7
- import { ToolResultOutput } from './content-part';
8
-
9
- describe('tool type', () => {
10
- describe('input type', () => {
11
- it('should work with fixed inputSchema', () => {
12
- const aTool = tool({
13
- inputSchema: z.object({ number: z.number() }),
14
- });
15
-
16
- expectTypeOf(aTool).toEqualTypeOf<Tool<{ number: number }, never>>();
17
- expectTypeOf(aTool.execute).toEqualTypeOf<undefined>();
18
- expectTypeOf(aTool.execute).not.toEqualTypeOf<Function>();
19
- expectTypeOf(aTool.inputSchema).toEqualTypeOf<
20
- FlexibleSchema<{ number: number }>
21
- >();
22
- });
23
-
24
- it('should work with flexible inputSchema', <T>() => {
25
- const aTool = tool({
26
- inputSchema: null as unknown as FlexibleSchema<T>,
27
- });
28
-
29
- expectTypeOf(aTool).toEqualTypeOf<Tool<T, never>>();
30
- expectTypeOf(aTool.execute).toEqualTypeOf<undefined>();
31
- expectTypeOf(aTool.execute).not.toEqualTypeOf<Function>();
32
- expectTypeOf(aTool.inputSchema).toEqualTypeOf<FlexibleSchema<T>>();
33
- });
34
-
35
- it('should infer input type correctly when inputExamples are present with optional/default zod schema', () => {
36
- const inputSchema = z.object({
37
- location: z.string(),
38
- unit: z.enum(['celsius', 'fahrenheit']).optional().default('celsius'),
39
- });
40
-
41
- tool({
42
- description: 'Get the weather for a location',
43
- inputSchema,
44
- inputExamples: [
45
- { input: { location: 'San Francisco', unit: 'celsius' } },
46
- ],
47
- execute: async input => {
48
- expectTypeOf(input).toEqualTypeOf<z.infer<typeof inputSchema>>();
49
- return { temperature: 20, unit: input.unit };
50
- },
51
- });
52
- });
53
-
54
- it('should infer input type correctly when inputExamples are present with refine zod schema', () => {
55
- const inputSchema = z.object({
56
- code: z.string().refine(val => val.length === 3),
57
- });
58
-
59
- tool({
60
- description: 'Get code details',
61
- inputSchema,
62
- inputExamples: [{ input: { code: 'ABC' } }],
63
- execute: async input => {
64
- expectTypeOf(input).toEqualTypeOf<z.infer<typeof inputSchema>>();
65
- return { valid: true };
66
- },
67
- });
68
- });
69
- });
70
-
71
- describe('output type', () => {
72
- it('should derive output type from execute function', () => {
73
- const aTool = tool({
74
- inputSchema: z.object({ number: z.number() }),
75
- execute: async input => {
76
- expectTypeOf(input).toEqualTypeOf<{ number: number }>();
77
- return 'test' as const;
78
- },
79
- });
80
-
81
- expectTypeOf(aTool).toEqualTypeOf<Tool<{ number: number }, 'test'>>();
82
- expectTypeOf(aTool.execute).toMatchTypeOf<
83
- ToolExecuteFunction<{ number: number }, 'test'> | undefined
84
- >();
85
- expectTypeOf(aTool.execute).not.toEqualTypeOf<undefined>();
86
- expectTypeOf(aTool.inputSchema).toEqualTypeOf<
87
- FlexibleSchema<{ number: number }>
88
- >();
89
- });
90
-
91
- it('should derive const schema from async generator execute function', () => {
92
- const aTool = tool({
93
- inputSchema: z.object({ number: z.number() }),
94
- execute: async function* () {
95
- yield 'test' as const;
96
- },
97
- });
98
-
99
- expectTypeOf(aTool).toEqualTypeOf<Tool<{ number: number }, 'test'>>();
100
- expectTypeOf(aTool.execute).toEqualTypeOf<
101
- ToolExecuteFunction<{ number: number }, 'test'> | undefined
102
- >();
103
- expectTypeOf(aTool.inputSchema).toEqualTypeOf<
104
- FlexibleSchema<{ number: number }>
105
- >();
106
- });
107
- });
108
-
109
- describe('toModelOutput', () => {
110
- it('should infer toModelOutput argument when there is only an input schema', () => {
111
- const aTool = tool({
112
- inputSchema: z.object({ number: z.number() }),
113
- toModelOutput: ({ output }) => {
114
- expectTypeOf(output).toEqualTypeOf<any>();
115
- return { type: 'text', value: 'test' };
116
- },
117
- });
118
-
119
- expectTypeOf(aTool.toModelOutput).toMatchTypeOf<
120
- | ((options: {
121
- toolCallId: string;
122
- input: { number: number };
123
- output: any;
124
- }) => ToolResultOutput | PromiseLike<ToolResultOutput>)
125
- | undefined
126
- >();
127
- });
128
-
129
- it('should infer toModelOutput argument when there is an execute function', () => {
130
- const aTool = tool({
131
- inputSchema: z.object({ number: z.number() }),
132
- execute: async () => 'test' as const,
133
- toModelOutput: ({ output }) => {
134
- expectTypeOf(output).toEqualTypeOf<'test'>();
135
- return { type: 'text', value: 'test' };
136
- },
137
- });
138
-
139
- expectTypeOf(aTool.toModelOutput).toMatchTypeOf<
140
- | ((options: {
141
- toolCallId: string;
142
- input: { number: number };
143
- output: 'test';
144
- }) => ToolResultOutput | PromiseLike<ToolResultOutput>)
145
- | undefined
146
- >();
147
- });
148
-
149
- it('should infer toModelOutput argument when there is an output schema', () => {
150
- const aTool = tool({
151
- inputSchema: z.object({ number: z.number() }),
152
- outputSchema: z.literal('test'),
153
- toModelOutput: ({ output }) => {
154
- expectTypeOf(output).toEqualTypeOf<'test'>();
155
- return { type: 'text', value: 'test' };
156
- },
157
- });
158
-
159
- expectTypeOf(aTool.toModelOutput).toMatchTypeOf<
160
- | ((options: {
161
- toolCallId: string;
162
- input: { number: number };
163
- output: 'test';
164
- }) => ToolResultOutput | PromiseLike<ToolResultOutput>)
165
- | undefined
166
- >();
167
- });
168
- });
169
-
170
- describe('needsApproval (function)', () => {
171
- it('should infer needsApproval argument when there is only an input schema', () => {
172
- const aTool = tool({
173
- inputSchema: z.object({ number: z.number() }),
174
- needsApproval: (input, options) => {
175
- expectTypeOf(input).toEqualTypeOf<{ number: number }>();
176
- expectTypeOf(options).toEqualTypeOf<{
177
- toolCallId: string;
178
- messages: ModelMessage[];
179
- experimental_context?: unknown;
180
- }>();
181
- return true;
182
- },
183
- });
184
-
185
- expectTypeOf(aTool.needsApproval).toMatchTypeOf<
186
- | boolean
187
- | ((
188
- input: { number: number },
189
- options: {
190
- toolCallId: string;
191
- messages: ModelMessage[];
192
- experimental_context: unknown;
193
- },
194
- ) => boolean | PromiseLike<boolean>)
195
- | undefined
196
- >();
197
- });
198
-
199
- it('should infer needsApproval argument when there is an execute function', () => {
200
- const aTool = tool({
201
- inputSchema: z.object({ number: z.number() }),
202
- execute: async () => 'test' as const,
203
- needsApproval: (input, options) => {
204
- expectTypeOf(input).toEqualTypeOf<{ number: number }>();
205
- expectTypeOf(options).toEqualTypeOf<{
206
- toolCallId: string;
207
- messages: ModelMessage[];
208
- experimental_context?: unknown;
209
- }>();
210
- return true;
211
- },
212
- });
213
-
214
- expectTypeOf(aTool.needsApproval).toMatchTypeOf<
215
- | boolean
216
- | ((
217
- input: { number: number },
218
- options: {
219
- toolCallId: string;
220
- messages: ModelMessage[];
221
- experimental_context: unknown;
222
- },
223
- ) => boolean | PromiseLike<boolean>)
224
- | undefined
225
- >();
226
- });
227
- });
228
- });
@@ -1,105 +0,0 @@
1
- import { TypeValidationError } from '@ai-sdk/provider';
2
- import { describe, expect, it } from 'vitest';
3
- import { safeValidateTypes, validateTypes } from './validate-types';
4
- import { StandardSchema } from './schema';
5
-
6
- const customSchema: StandardSchema<{ name: string; age: number }> = {
7
- '~standard': {
8
- version: 1,
9
- vendor: 'custom',
10
- validate: async (value: any) => {
11
- return typeof value === 'object' &&
12
- value !== null &&
13
- 'name' in value &&
14
- typeof value.name === 'string' &&
15
- 'age' in value &&
16
- typeof value.age === 'number'
17
- ? { value }
18
- : { issues: [new Error('Invalid input')] };
19
- },
20
- jsonSchema: {
21
- input: () => ({
22
- type: 'object',
23
- properties: {
24
- name: { type: 'string' },
25
- age: { type: 'number' },
26
- },
27
- }),
28
- output: () => ({
29
- type: 'object',
30
- properties: {
31
- name: { type: 'string' },
32
- age: { type: 'number' },
33
- },
34
- }),
35
- },
36
- },
37
- };
38
-
39
- describe('validateTypes', () => {
40
- it('should return validated object for valid input', async () => {
41
- const input = { name: 'John', age: 30 };
42
- expect(await validateTypes({ value: input, schema: customSchema })).toEqual(
43
- input,
44
- );
45
- });
46
-
47
- it('should throw TypeValidationError for invalid input', async () => {
48
- const input = { name: 'John', age: '30' };
49
-
50
- try {
51
- await validateTypes({
52
- value: input,
53
- schema: customSchema,
54
- });
55
- expect.fail('Expected TypeValidationError to be thrown');
56
- } catch (error) {
57
- expect(error).toBeInstanceOf(TypeValidationError);
58
-
59
- const typedError = error as TypeValidationError;
60
-
61
- expect({
62
- name: typedError.name,
63
- value: typedError.value,
64
- cause: typedError.cause,
65
- message: typedError.message,
66
- }).toStrictEqual({
67
- name: 'AI_TypeValidationError',
68
- value: input,
69
- cause: [expect.any(Error)],
70
- message: expect.stringContaining('Type validation failed'),
71
- });
72
- }
73
- });
74
- });
75
-
76
- describe('safeValidateTypes', () => {
77
- it('should return validated object for valid input', async () => {
78
- const input = { name: 'John', age: 30 };
79
- const result = await safeValidateTypes({
80
- value: input,
81
- schema: customSchema,
82
- });
83
- expect(result).toEqual({ success: true, value: input, rawValue: input });
84
- });
85
-
86
- it('should return error object for invalid input', async () => {
87
- const input = { name: 'John', age: '30' };
88
- const result = await safeValidateTypes({
89
- value: input,
90
- schema: customSchema,
91
- });
92
-
93
- expect(result).toEqual({
94
- success: false,
95
- error: expect.any(TypeValidationError),
96
- rawValue: input,
97
- });
98
-
99
- if (!result.success) {
100
- expect(result.error).toBeInstanceOf(TypeValidationError);
101
- expect(result.error.value).toEqual(input);
102
- expect(result.error.message).toContain('Type validation failed');
103
- }
104
- });
105
- });
@@ -1,84 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
-
3
- import { withUserAgentSuffix } from './with-user-agent-suffix';
4
-
5
- describe('withUserAgentSuffix', () => {
6
- it('should create a new user-agent header when no existing user-agent exists', () => {
7
- const headers = {
8
- 'content-type': 'application/json',
9
- authorization: 'Bearer token123',
10
- };
11
-
12
- const result = withUserAgentSuffix(
13
- headers,
14
- 'ai-sdk/0.0.0-test',
15
- 'provider/test-openai',
16
- );
17
-
18
- expect(result['user-agent']).toBe('ai-sdk/0.0.0-test provider/test-openai');
19
- expect(result['content-type']).toBe('application/json');
20
- expect(result['authorization']).toBe('Bearer token123');
21
- });
22
-
23
- it('should append suffix parts to existing user-agent header', () => {
24
- const headers = {
25
- 'user-agent': 'TestApp/0.0.0-test',
26
- accept: 'application/json',
27
- };
28
-
29
- const result = withUserAgentSuffix(
30
- headers,
31
- 'ai-sdk/0.0.0-test',
32
- 'provider/test-anthropic',
33
- );
34
-
35
- expect(result['user-agent']).toBe(
36
- 'TestApp/0.0.0-test ai-sdk/0.0.0-test provider/test-anthropic',
37
- );
38
- expect(result['accept']).toBe('application/json');
39
- });
40
-
41
- it('should automatically remove undefined entries from headers', () => {
42
- const headers = {
43
- 'content-type': 'application/json',
44
- authorization: undefined,
45
- 'user-agent': 'TestApp/0.0.0-test',
46
- accept: 'application/json',
47
- 'cache-control': null,
48
- };
49
-
50
- const result = withUserAgentSuffix(headers as any, 'ai-sdk/0.0.0-test');
51
-
52
- expect(result['user-agent']).toBe('TestApp/0.0.0-test ai-sdk/0.0.0-test');
53
- expect(result['content-type']).toBe('application/json');
54
- expect(result['accept']).toBe('application/json');
55
- expect(result['authorization']).toBeUndefined();
56
- expect(result['cache-control']).toBeUndefined();
57
- });
58
-
59
- it('should preserve headers when given a Headers instance', () => {
60
- const headers = new Headers({
61
- Authorization: 'Bearer token123',
62
- 'X-Custom': 'value',
63
- });
64
-
65
- const result = withUserAgentSuffix(headers, 'ai-sdk/0.0.0-test');
66
-
67
- expect(result['authorization']).toBe('Bearer token123');
68
- expect(result['x-custom']).toBe('value');
69
- expect(result['user-agent']).toBe('ai-sdk/0.0.0-test');
70
- });
71
-
72
- it('should handle array header entries', () => {
73
- const headers: HeadersInit = [
74
- ['Authorization', 'Bearer token123'],
75
- ['X-Feature', 'alpha'],
76
- ];
77
-
78
- const result = withUserAgentSuffix(headers, 'ai-sdk/0.0.0-test');
79
-
80
- expect(result['authorization']).toBe('Bearer token123');
81
- expect(result['x-feature']).toBe('alpha');
82
- expect(result['user-agent']).toBe('ai-sdk/0.0.0-test');
83
- });
84
- });