From 2481d447726c44872c1e11613881649d3c130609 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 13 May 2025 12:53:50 -0400 Subject: [PATCH 1/2] feat(ai): Add support for `minItems` and `maxItems` to `Schema` --- .changeset/angry-scissors-sit.md | 6 ++ common/api-review/ai.api.md | 5 ++ .../ai/src/requests/schema-builder.test.ts | 87 +++++++++++++++++++ packages/ai/src/requests/schema-builder.ts | 8 +- packages/ai/src/types/schema.ts | 6 +- 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 .changeset/angry-scissors-sit.md diff --git a/.changeset/angry-scissors-sit.md b/.changeset/angry-scissors-sit.md new file mode 100644 index 00000000000..8aeb7dcaf52 --- /dev/null +++ b/.changeset/angry-scissors-sit.md @@ -0,0 +1,6 @@ +--- +'firebase': minor +'@firebase/ai': minor +--- + +Add support for `minItems` and `maxItems` to `Schema`. diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index d096d4c27f6..6af44fd13b5 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -790,6 +790,9 @@ export abstract class Schema implements SchemaInterface { format?: string; // (undocumented) static integer(integerParams?: SchemaParams): IntegerSchema; + items?: SchemaInterface; + maxItems?: number; + minItems?: number; nullable: boolean; // (undocumented) static number(numberParams?: SchemaParams): NumberSchema; @@ -831,6 +834,8 @@ export interface SchemaShared { example?: unknown; format?: string; items?: T; + maxItems?: number; + minItems?: number; nullable?: boolean; properties?: { [k: string]: T; diff --git a/packages/ai/src/requests/schema-builder.test.ts b/packages/ai/src/requests/schema-builder.test.ts index d05b81381ea..257045f5be7 100644 --- a/packages/ai/src/requests/schema-builder.test.ts +++ b/packages/ai/src/requests/schema-builder.test.ts @@ -81,6 +81,93 @@ describe('Schema builder', () => { nullable: false }); }); + describe('Schema.array', () => { + it('builds an array schema with basic items', () => { + const schema = Schema.array({ + items: Schema.string() + }); + expect(schema.toJSON()).to.eql({ + type: 'array', + nullable: false, + items: { + type: 'string', + nullable: false + } + }); + }); + + it('builds an array schema with items and minItems', () => { + const schema = Schema.array({ + items: Schema.number(), + minItems: 1 + }); + expect(schema.toJSON()).to.eql({ + type: 'array', + nullable: false, + items: { + type: 'number', + nullable: false + }, + minItems: 1 + }); + }); + + it('builds an array schema with items and maxItems', () => { + const schema = Schema.array({ + items: Schema.boolean(), + maxItems: 10 + }); + expect(schema.toJSON()).to.eql({ + type: 'array', + nullable: false, + items: { + type: 'boolean', + nullable: false + }, + maxItems: 10 + }); + }); + + it('builds an array schema with items, minItems, and maxItems', () => { + const schema = Schema.array({ + items: Schema.integer(), + minItems: 0, + maxItems: 5 + }); + expect(schema.toJSON()).to.eql({ + type: 'array', + nullable: false, + items: { + type: 'integer', + nullable: false + }, + minItems: 0, + maxItems: 5 + }); + }); + + it('builds an array schema with items, minItems, maxItems, and other options', () => { + const schema = Schema.array({ + items: Schema.string({ description: 'A list of names' }), + minItems: 1, + maxItems: 3, + nullable: true, + description: 'An array of strings' + }); + expect(schema.toJSON()).to.eql({ + type: 'array', + nullable: true, + description: 'An array of strings', + items: { + type: 'string', + description: 'A list of names', + nullable: false + }, + minItems: 1, + maxItems: 3 + }); + }); + }); it('builds an object schema', () => { const schema = Schema.object({ properties: { diff --git a/packages/ai/src/requests/schema-builder.ts b/packages/ai/src/requests/schema-builder.ts index 524cfdb1c20..5fbe14b358b 100644 --- a/packages/ai/src/requests/schema-builder.ts +++ b/packages/ai/src/requests/schema-builder.ts @@ -49,6 +49,12 @@ export abstract class Schema implements SchemaInterface { format?: string; /** Optional. The description of the property. */ description?: string; + /** Optional. The items of the property. */ + items?: SchemaInterface; + /** The minimum number of items (elements) in a schema of type {@link SchemaType.ARRAY}. */ + minItems?: number; + /** The maximum number of items (elements) in a schema of type {@link SchemaType.ARRAY}. */ + maxItems?: number; /** Optional. Whether the property is nullable. Defaults to false. */ nullable: boolean; /** Optional. The example of the property. */ @@ -77,7 +83,7 @@ export abstract class Schema implements SchemaInterface { * @internal */ toJSON(): SchemaRequest { - const obj: { type: SchemaType; [key: string]: unknown } = { + const obj: { type: SchemaType;[key: string]: unknown } = { type: this.type }; for (const prop in this) { diff --git a/packages/ai/src/types/schema.ts b/packages/ai/src/types/schema.ts index e9fe9286b61..d81998ec779 100644 --- a/packages/ai/src/types/schema.ts +++ b/packages/ai/src/types/schema.ts @@ -51,6 +51,10 @@ export interface SchemaShared { description?: string; /** Optional. The items of the property. */ items?: T; + /** The minimum number of items (elements) in a schema of type {@link SchemaType.ARRAY}. */ + minItems?: number; + /** The maximum number of items (elements) in a schema of type {@link SchemaType.ARRAY}. */ + maxItems?: number; /** Optional. Map of `Schema` objects. */ properties?: { [k: string]: T; @@ -69,7 +73,7 @@ export interface SchemaShared { * {@link Schema} classes. * @public */ -export interface SchemaParams extends SchemaShared {} +export interface SchemaParams extends SchemaShared { } /** * Final format for {@link Schema} params passed to backend requests. From c5089e2cf96a027223299ca8ed76d68afad40882 Mon Sep 17 00:00:00 2001 From: Daniel La Rocque Date: Tue, 13 May 2025 13:11:23 -0400 Subject: [PATCH 2/2] update docs and format --- docs-devsite/ai.schema.md | 33 ++++++++++++++++++++++ docs-devsite/ai.schemashared.md | 22 +++++++++++++++ packages/ai/src/requests/schema-builder.ts | 2 +- packages/ai/src/types/schema.ts | 2 +- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/docs-devsite/ai.schema.md b/docs-devsite/ai.schema.md index b0681b0cdf3..fa1225c91e5 100644 --- a/docs-devsite/ai.schema.md +++ b/docs-devsite/ai.schema.md @@ -32,6 +32,9 @@ export declare abstract class Schema implements SchemaInterface | [description](./ai.schema.md#schemadescription) | | string | Optional. The description of the property. | | [example](./ai.schema.md#schemaexample) | | unknown | Optional. The example of the property. | | [format](./ai.schema.md#schemaformat) | | string | Optional. The format of the property. Supported formats:
  • for NUMBER type: "float", "double"
  • for INTEGER type: "int32", "int64"
  • for STRING type: "email", "byte", etc
| +| [items](./ai.schema.md#schemaitems) | | [SchemaInterface](./ai.schemainterface.md#schemainterface_interface) | Optional. The items of the property. | +| [maxItems](./ai.schema.md#schemamaxitems) | | number | The maximum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). | +| [minItems](./ai.schema.md#schemaminitems) | | number | The minimum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). | | [nullable](./ai.schema.md#schemanullable) | | boolean | Optional. Whether the property is nullable. Defaults to false. | | [type](./ai.schema.md#schematype) | | [SchemaType](./ai.md#schematype) | Optional. The type of the property. [SchemaType](./ai.md#schematype). | @@ -93,6 +96,36 @@ Optional. The format of the property. Supported formats:
  • for NUMBE format?: string; ``` +## Schema.items + +Optional. The items of the property. + +Signature: + +```typescript +items?: SchemaInterface; +``` + +## Schema.maxItems + +The maximum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). + +Signature: + +```typescript +maxItems?: number; +``` + +## Schema.minItems + +The minimum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). + +Signature: + +```typescript +minItems?: number; +``` + ## Schema.nullable Optional. Whether the property is nullable. Defaults to false. diff --git a/docs-devsite/ai.schemashared.md b/docs-devsite/ai.schemashared.md index eba57f82935..0b122d9ca18 100644 --- a/docs-devsite/ai.schemashared.md +++ b/docs-devsite/ai.schemashared.md @@ -27,6 +27,8 @@ export interface SchemaShared | [example](./ai.schemashared.md#schemasharedexample) | unknown | Optional. The example of the property. | | [format](./ai.schemashared.md#schemasharedformat) | string | Optional. The format of the property. When using the Gemini Developer API ([GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class)), this must be either 'enum' or 'date-time', otherwise requests will fail. | | [items](./ai.schemashared.md#schemashareditems) | T | Optional. The items of the property. | +| [maxItems](./ai.schemashared.md#schemasharedmaxitems) | number | The maximum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). | +| [minItems](./ai.schemashared.md#schemasharedminitems) | number | The minimum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). | | [nullable](./ai.schemashared.md#schemasharednullable) | boolean | Optional. Whether the property is nullable. | | [properties](./ai.schemashared.md#schemasharedproperties) | { \[k: string\]: T; } | Optional. Map of Schema objects. | @@ -80,6 +82,26 @@ Optional. The items of the property. items?: T; ``` +## SchemaShared.maxItems + +The maximum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). + +Signature: + +```typescript +maxItems?: number; +``` + +## SchemaShared.minItems + +The minimum number of items (elements) in a schema of type [SchemaType.ARRAY](./ai.md#schematypearray_enummember). + +Signature: + +```typescript +minItems?: number; +``` + ## SchemaShared.nullable Optional. Whether the property is nullable. diff --git a/packages/ai/src/requests/schema-builder.ts b/packages/ai/src/requests/schema-builder.ts index 5fbe14b358b..7d9ece462b3 100644 --- a/packages/ai/src/requests/schema-builder.ts +++ b/packages/ai/src/requests/schema-builder.ts @@ -83,7 +83,7 @@ export abstract class Schema implements SchemaInterface { * @internal */ toJSON(): SchemaRequest { - const obj: { type: SchemaType;[key: string]: unknown } = { + const obj: { type: SchemaType; [key: string]: unknown } = { type: this.type }; for (const prop in this) { diff --git a/packages/ai/src/types/schema.ts b/packages/ai/src/types/schema.ts index d81998ec779..5bad3ce648d 100644 --- a/packages/ai/src/types/schema.ts +++ b/packages/ai/src/types/schema.ts @@ -73,7 +73,7 @@ export interface SchemaShared { * {@link Schema} classes. * @public */ -export interface SchemaParams extends SchemaShared { } +export interface SchemaParams extends SchemaShared {} /** * Final format for {@link Schema} params passed to backend requests.