@ai-sdk/google 4.0.39 → 4.0.41

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/google",
3
- "version": "4.0.39",
3
+ "version": "4.0.41",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@ai-sdk/provider": "4.0.7",
39
- "@ai-sdk/provider-utils": "5.0.25"
39
+ "@ai-sdk/provider-utils": "5.0.26"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "22.19.19",
@@ -1,4 +1,8 @@
1
- import type { JSONSchema7Definition } from '@ai-sdk/provider';
1
+ import {
2
+ UnsupportedFunctionalityError,
3
+ type JSONSchema7,
4
+ type JSONSchema7Definition,
5
+ } from '@ai-sdk/provider';
2
6
 
3
7
  /**
4
8
  * Converts JSON Schema 7 to OpenAPI Schema 3.0
@@ -48,10 +52,6 @@ export function convertJSONSchemaToOpenAPISchema(
48
52
  if (required) result.required = required;
49
53
  if (format) result.format = format;
50
54
 
51
- if (constValue !== undefined) {
52
- result.enum = [constValue];
53
- }
54
-
55
55
  // Handle type
56
56
  if (type) {
57
57
  if (Array.isArray(type)) {
@@ -73,9 +73,11 @@ export function convertJSONSchemaToOpenAPISchema(
73
73
  }
74
74
  }
75
75
 
76
- // Handle enum
77
- if (enumValues !== undefined) {
78
- result.enum = enumValues;
76
+ const values =
77
+ enumValues ?? (constValue !== undefined ? [constValue] : undefined);
78
+
79
+ if (values !== undefined) {
80
+ addEnumToSchema({ values, type, result });
79
81
  }
80
82
 
81
83
  if (properties != null) {
@@ -146,6 +148,123 @@ export function convertJSONSchemaToOpenAPISchema(
146
148
  return result;
147
149
  }
148
150
 
151
+ type EnumValues = NonNullable<JSONSchema7['enum']>;
152
+ type EnumType = 'string' | 'number' | 'integer' | 'boolean';
153
+ type GoogleEnumSchema = {
154
+ type?: JSONSchema7['type'];
155
+ enum?: JSONSchema7['enum'];
156
+ format?: JSONSchema7['format'];
157
+ anyOf?: JSONSchema7['anyOf'];
158
+ nullable?: boolean;
159
+ };
160
+
161
+ function addEnumToSchema({
162
+ values,
163
+ type,
164
+ result,
165
+ }: {
166
+ values: EnumValues;
167
+ type: JSONSchema7['type'];
168
+ result: GoogleEnumSchema;
169
+ }) {
170
+ const nullable =
171
+ (Array.isArray(type) && type.includes('null')) ||
172
+ (type === undefined && values.includes(null));
173
+
174
+ // Gemini uses nullable instead of a null enum member.
175
+ const enumValues = nullable ? values.filter(value => value !== null) : values;
176
+
177
+ if (values.length > 0 && values.every(value => value === null)) {
178
+ const typeAllowsNull =
179
+ type === undefined ||
180
+ type === 'null' ||
181
+ (Array.isArray(type) && type.includes('null'));
182
+
183
+ if (typeAllowsNull) {
184
+ result.type = 'null';
185
+ if (Array.isArray(type)) {
186
+ delete result.anyOf;
187
+ }
188
+ return;
189
+ }
190
+ }
191
+
192
+ const enumType = getEnumType({ values: enumValues, type });
193
+
194
+ if (enumType === undefined) {
195
+ throw new UnsupportedFunctionalityError({
196
+ functionality: 'JSON Schema enum with mixed or unsupported values',
197
+ message:
198
+ 'Google does not support this JSON Schema enum. Enum values must share one supported primitive type and match the schema type.',
199
+ });
200
+ }
201
+
202
+ result.type = enumType;
203
+
204
+ // The earlier type-array conversion created anyOf. The enum gives us one
205
+ // concrete value type, so store that type directly.
206
+ if (Array.isArray(type)) {
207
+ delete result.anyOf;
208
+ }
209
+
210
+ if (nullable) {
211
+ result.nullable = true;
212
+ }
213
+
214
+ if (enumType === 'string') {
215
+ result.enum = enumValues;
216
+ } else {
217
+ result.format = 'enum';
218
+ result.enum = enumValues.map(String);
219
+ }
220
+ }
221
+
222
+ function getEnumType({
223
+ values,
224
+ type,
225
+ }: {
226
+ values: EnumValues;
227
+ type: JSONSchema7['type'];
228
+ }): EnumType | undefined {
229
+ if (values.length === 0) {
230
+ return undefined;
231
+ }
232
+
233
+ const typeAllows = (enumType: EnumType) =>
234
+ type === undefined ||
235
+ type === enumType ||
236
+ (Array.isArray(type) && type.includes(enumType));
237
+
238
+ if (
239
+ typeAllows('string') &&
240
+ values.every(value => typeof value === 'string')
241
+ ) {
242
+ return 'string';
243
+ }
244
+
245
+ if (
246
+ (typeAllows('number') || typeAllows('integer')) &&
247
+ values.every(value => typeof value === 'number' && Number.isFinite(value))
248
+ ) {
249
+ if (typeAllows('number')) {
250
+ return 'number';
251
+ }
252
+
253
+ if (values.every(value => Number.isInteger(value))) {
254
+ return 'integer';
255
+ }
256
+ }
257
+
258
+ if (
259
+ typeAllows('boolean') &&
260
+ values.every(value => typeof value === 'boolean')
261
+ ) {
262
+ return 'boolean';
263
+ }
264
+
265
+ return undefined;
266
+ }
267
+
149
268
  function isEmptyObjectSchema(jsonSchema: JSONSchema7Definition): boolean {
150
269
  return (
151
270
  jsonSchema != null &&
@@ -13,6 +13,7 @@ const googleErrorDataSchema = lazySchema(() =>
13
13
  code: z.number().nullable(),
14
14
  message: z.string(),
15
15
  status: z.string(),
16
+ details: z.array(z.unknown()).nullish(),
16
17
  }),
17
18
  }),
18
19
  ),