@ai-sdk/provider-utils 4.0.8 → 4.0.9

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 (55) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.js +1 -1
  3. package/dist/index.mjs +1 -1
  4. package/package.json +6 -2
  5. package/src/__snapshots__/schema.test.ts.snap +0 -346
  6. package/src/add-additional-properties-to-json-schema.test.ts +0 -289
  7. package/src/convert-async-iterator-to-readable-stream.test.ts +0 -78
  8. package/src/convert-image-model-file-to-data-uri.test.ts +0 -85
  9. package/src/convert-to-form-data.test.ts +0 -167
  10. package/src/create-tool-name-mapping.test.ts +0 -163
  11. package/src/delay.test.ts +0 -212
  12. package/src/delayed-promise.test.ts +0 -132
  13. package/src/download-blob.test.ts +0 -145
  14. package/src/generate-id.test.ts +0 -31
  15. package/src/get-from-api.test.ts +0 -199
  16. package/src/get-runtime-environment-user-agent.test.ts +0 -47
  17. package/src/inject-json-instruction.test.ts +0 -404
  18. package/src/is-url-supported.test.ts +0 -282
  19. package/src/media-type-to-extension.test.ts +0 -26
  20. package/src/normalize-headers.test.ts +0 -64
  21. package/src/parse-json.test.ts +0 -191
  22. package/src/remove-undefined-entries.test.ts +0 -57
  23. package/src/resolve.test.ts +0 -125
  24. package/src/response-handler.test.ts +0 -89
  25. package/src/schema.test-d.ts +0 -11
  26. package/src/schema.test.ts +0 -502
  27. package/src/secure-json-parse.test.ts +0 -59
  28. package/src/to-json-schema/zod3-to-json-schema/parse-def.test.ts +0 -224
  29. package/src/to-json-schema/zod3-to-json-schema/parsers/array.test.ts +0 -98
  30. package/src/to-json-schema/zod3-to-json-schema/parsers/bigint.test.ts +0 -51
  31. package/src/to-json-schema/zod3-to-json-schema/parsers/branded.test.ts +0 -16
  32. package/src/to-json-schema/zod3-to-json-schema/parsers/catch.test.ts +0 -15
  33. package/src/to-json-schema/zod3-to-json-schema/parsers/date.test.ts +0 -97
  34. package/src/to-json-schema/zod3-to-json-schema/parsers/default.test.ts +0 -54
  35. package/src/to-json-schema/zod3-to-json-schema/parsers/effects.test.ts +0 -41
  36. package/src/to-json-schema/zod3-to-json-schema/parsers/intersection.test.ts +0 -92
  37. package/src/to-json-schema/zod3-to-json-schema/parsers/map.test.ts +0 -48
  38. package/src/to-json-schema/zod3-to-json-schema/parsers/native-enum.test.ts +0 -102
  39. package/src/to-json-schema/zod3-to-json-schema/parsers/nullable.test.ts +0 -67
  40. package/src/to-json-schema/zod3-to-json-schema/parsers/number.test.ts +0 -65
  41. package/src/to-json-schema/zod3-to-json-schema/parsers/object.test.ts +0 -149
  42. package/src/to-json-schema/zod3-to-json-schema/parsers/optional.test.ts +0 -147
  43. package/src/to-json-schema/zod3-to-json-schema/parsers/pipe.test.ts +0 -35
  44. package/src/to-json-schema/zod3-to-json-schema/parsers/promise.test.ts +0 -15
  45. package/src/to-json-schema/zod3-to-json-schema/parsers/readonly.test.ts +0 -20
  46. package/src/to-json-schema/zod3-to-json-schema/parsers/record.test.ts +0 -108
  47. package/src/to-json-schema/zod3-to-json-schema/parsers/set.test.ts +0 -20
  48. package/src/to-json-schema/zod3-to-json-schema/parsers/string.test.ts +0 -438
  49. package/src/to-json-schema/zod3-to-json-schema/parsers/tuple.test.ts +0 -33
  50. package/src/to-json-schema/zod3-to-json-schema/parsers/union.test.ts +0 -226
  51. package/src/to-json-schema/zod3-to-json-schema/refs.test.ts +0 -919
  52. package/src/to-json-schema/zod3-to-json-schema/zod3-to-json-schema.test.ts +0 -862
  53. package/src/types/tool.test-d.ts +0 -228
  54. package/src/validate-types.test.ts +0 -105
  55. 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
- });