diff --git a/FirebaseAI/Sources/Types/Public/Schema.swift b/FirebaseAI/Sources/Types/Public/Schema.swift index f5a378a4c11..b8b2ba6c16e 100644 --- a/FirebaseAI/Sources/Types/Public/Schema.swift +++ b/FirebaseAI/Sources/Types/Public/Schema.swift @@ -167,6 +167,7 @@ public final class Schema: Sendable { /// - Parameters: /// - description: An optional description of what the string should contain or represent; may /// use Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it *may* generate `null` instead of a /// string; defaults to `false`, enforcing that a string value is generated. /// - format: An optional modifier describing the expected format of the string. Currently no @@ -174,12 +175,13 @@ public final class Schema: Sendable { /// ``StringFormat/custom(_:)``, for example `.custom("email")` or `.custom("byte")`; these /// provide additional hints for how the model should respond but are not guaranteed to be /// adhered to. - public static func string(description: String? = nil, nullable: Bool = false, - format: StringFormat? = nil) -> Schema { + public static func string(description: String? = nil, title: String? = nil, + nullable: Bool = false, format: StringFormat? = nil) -> Schema { return self.init( type: .string, format: format?.rawValue, description: description, + title: title, nullable: nullable ) } @@ -202,15 +204,17 @@ public final class Schema: Sendable { /// - values: The list of string values that may be generated by the model. /// - description: An optional description of what the `values` contain or represent; may use /// Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it *may* generate `null` instead of one of /// the strings specified in `values`; defaults to `false`, enforcing that one of the string /// values is generated. public static func enumeration(values: [String], description: String? = nil, - nullable: Bool = false) -> Schema { + title: String? = nil, nullable: Bool = false) -> Schema { return self.init( type: .string, format: "enum", description: description, + title: title, nullable: nullable, enumValues: values ) @@ -229,18 +233,20 @@ public final class Schema: Sendable { /// - Parameters: /// - description: An optional description of what the number should contain or represent; may /// use Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it may generate `null` instead of a number; /// defaults to `false`, enforcing that a number is generated. /// - minimum: If specified, instructs the model that the value should be greater than or /// equal to the specified minimum. /// - maximum: If specified, instructs the model that the value should be less than or equal /// to the specified maximum. - public static func float(description: String? = nil, nullable: Bool = false, + public static func float(description: String? = nil, title: String? = nil, nullable: Bool = false, minimum: Float? = nil, maximum: Float? = nil) -> Schema { return self.init( type: .number, format: "float", description: description, + title: title, nullable: nullable, minimum: minimum.map { Double($0) }, maximum: maximum.map { Double($0) } @@ -255,17 +261,20 @@ public final class Schema: Sendable { /// - Parameters: /// - description: An optional description of what the number should contain or represent; may /// use Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it may return `null` instead of a number; /// defaults to `false`, enforcing that a number is returned. /// - minimum: If specified, instructs the model that the value should be greater than or /// equal to the specified minimum. /// - maximum: If specified, instructs the model that the value should be less than or equal /// to the specified maximum. - public static func double(description: String? = nil, nullable: Bool = false, + public static func double(description: String? = nil, title: String? = nil, + nullable: Bool = false, minimum: Double? = nil, maximum: Double? = nil) -> Schema { return self.init( type: .number, description: description, + title: title, nullable: nullable, minimum: minimum, maximum: maximum @@ -287,6 +296,7 @@ public final class Schema: Sendable { /// - Parameters: /// - description: An optional description of what the integer should contain or represent; may /// use Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it may return `null` instead of an integer; /// defaults to `false`, enforcing that an integer is returned. /// - format: An optional modifier describing the expected format of the integer. Currently the @@ -296,13 +306,14 @@ public final class Schema: Sendable { /// equal to the specified minimum. /// - maximum: If specified, instructs the model that the value should be less than or equal /// to the specified maximum. - public static func integer(description: String? = nil, nullable: Bool = false, - format: IntegerFormat? = nil, + public static func integer(description: String? = nil, title: String? = nil, + nullable: Bool = false, format: IntegerFormat? = nil, minimum: Int? = nil, maximum: Int? = nil) -> Schema { return self.init( type: .integer, format: format?.rawValue, description: description, + title: title, nullable: nullable.self, minimum: minimum.map { Double($0) }, maximum: maximum.map { Double($0) } @@ -317,10 +328,12 @@ public final class Schema: Sendable { /// - Parameters: /// - description: An optional description of what the boolean should contain or represent; may /// use Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it may return `null` instead of a boolean; /// defaults to `false`, enforcing that a boolean is returned. - public static func boolean(description: String? = nil, nullable: Bool = false) -> Schema { - return self.init(type: .boolean, description: description, nullable: nullable) + public static func boolean(description: String? = nil, title: String? = nil, + nullable: Bool = false) -> Schema { + return self.init(type: .boolean, description: description, title: title, nullable: nullable) } /// Returns a `Schema` representing an array. @@ -334,17 +347,20 @@ public final class Schema: Sendable { /// - items: The `Schema` of the elements that the array will hold. /// - description: An optional description of what the array should contain or represent; may /// use Markdown format. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it may return `null` instead of an array; /// defaults to `false`, enforcing that an array is returned. /// - minItems: Instructs the model to produce at least the specified minimum number of elements /// in the array; defaults to `nil`, meaning any number. /// - maxItems: Instructs the model to produce at most the specified maximum number of elements /// in the array. - public static func array(items: Schema, description: String? = nil, nullable: Bool = false, - minItems: Int? = nil, maxItems: Int? = nil) -> Schema { + public static func array(items: Schema, description: String? = nil, title: String? = nil, + nullable: Bool = false, minItems: Int? = nil, + maxItems: Int? = nil) -> Schema { return self.init( type: .array, description: description, + title: title, nullable: nullable, items: items, minItems: minItems, @@ -384,7 +400,7 @@ public final class Schema: Sendable { /// generated JSON string. See ``propertyOrdering`` for details. /// - description: An optional description of what the object should contain or represent; may /// use Markdown format. - /// - title: An optional human-readable name/summary for the object schema. + /// - title: An optional human-readable name/summary for the schema. /// - nullable: If `true`, instructs the model that it may return `null` instead of an object; /// defaults to `false`, enforcing that an object is returned. public static func object(properties: [String: Schema], optionalProperties: [String] = [], diff --git a/FirebaseAI/Tests/Unit/Types/SchemaTests.swift b/FirebaseAI/Tests/Unit/Types/SchemaTests.swift index e6eb839a39a..bd8d595dd24 100644 --- a/FirebaseAI/Tests/Unit/Types/SchemaTests.swift +++ b/FirebaseAI/Tests/Unit/Types/SchemaTests.swift @@ -43,8 +43,14 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_string_allOptions() throws { let description = "Timestamp of the event." + let title = "Event Timestamp" let format = Schema.StringFormat.custom("date-time") - let schema = Schema.string(description: description, nullable: true, format: format) + let schema = Schema.string( + description: description, + title: title, + nullable: true, + format: format + ) let jsonData = try encoder.encode(schema) @@ -54,6 +60,7 @@ final class SchemaTests: XCTestCase { "description" : "\(description)", "format" : "date-time", "nullable" : true, + "title": "\(title)", "type" : "STRING" } """) @@ -85,7 +92,13 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_enumeration_allOptions() throws { let values = ["NORTH", "SOUTH", "EAST", "WEST"] let description = "Compass directions." - let schema = Schema.enumeration(values: values, description: description, nullable: true) + let title = "Directions" + let schema = Schema.enumeration( + values: values, + description: description, + title: title, + nullable: true + ) let jsonData = try encoder.encode(schema) @@ -101,6 +114,7 @@ final class SchemaTests: XCTestCase { ], "format" : "enum", "nullable" : true, + "title": "\(title)", "type" : "STRING" } """) @@ -125,10 +139,12 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_float_allOptions() throws { let description = "Temperature in Celsius." + let title = "Temperature (°C)" let minimum: Float = -40.25 let maximum: Float = 50.5 let schema = Schema.float( description: description, + title: title, nullable: true, minimum: minimum, maximum: maximum @@ -144,6 +160,7 @@ final class SchemaTests: XCTestCase { "maximum" : \(maximum), "minimum" : \(minimum), "nullable" : true, + "title": "\(title)", "type" : "NUMBER" } """) @@ -167,10 +184,12 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_double_allOptions() throws { let description = "Account balance." + let title = "Balance" let minimum = 0.01 let maximum = 1_000_000.99 let schema = Schema.double( description: description, + title: title, nullable: true, minimum: minimum, maximum: maximum @@ -185,6 +204,7 @@ final class SchemaTests: XCTestCase { "maximum" : \(maximum), "minimum" : \(minimum), "nullable" : true, + "title": "\(title)", "type" : "NUMBER" } """) @@ -208,11 +228,13 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_integer_allOptions() throws { let description = "User age." + let title = "Age" let minimum = 0 let maximum = 120 let format = Schema.IntegerFormat.int32 let schema = Schema.integer( description: description, + title: title, nullable: true, format: format, minimum: minimum, @@ -229,6 +251,7 @@ final class SchemaTests: XCTestCase { "maximum" : \(maximum), "minimum" : \(minimum), "nullable" : true, + "title": "\(title)", "type" : "INTEGER" } """) @@ -252,7 +275,8 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_boolean_allOptions() throws { let description = "Is the user an administrator?" - let schema = Schema.boolean(description: description, nullable: true) + let title = "Administrator Check" + let schema = Schema.boolean(description: description, title: title, nullable: true) let jsonData = try encoder.encode(schema) @@ -261,6 +285,7 @@ final class SchemaTests: XCTestCase { { "description" : "\(description)", "nullable" : true, + "title": "\(title)", "type" : "BOOLEAN" } """) @@ -290,11 +315,13 @@ final class SchemaTests: XCTestCase { func testEncodeSchema_array_allOptions() throws { let itemsSchema = Schema.integer(format: .int64) let description = "List of product IDs." + let title = "Product IDs" let minItems = 1 let maxItems = 10 let schema = Schema.array( items: itemsSchema, description: description, + title: title, nullable: true, minItems: minItems, maxItems: maxItems @@ -314,6 +341,7 @@ final class SchemaTests: XCTestCase { "maxItems" : \(maxItems), "minItems" : \(minItems), "nullable" : true, + "title": "\(title)", "type" : "ARRAY" } """)