Files
Andrew Heard 4a4d0fa518 feat(ai): add Gemini API Swift data model generator (#16879)
Add the Python pipeline under `GeminiLanguageModel/scripts/typegen` that
generates the Swift data models in `GeminiAPIDataModels/GenerateContent`
from the Firebase AI Logic Google Discovery Document, so the models can
be regenerated in-tree as the upstream API evolves.
- `upgrade_spec.py` fetches the `v1beta` Discovery Document, converts it
  to OpenAPI 3.1.0, extracts shared standalone enums per backend, infers
  required properties, and merges the schema overrides from
  `discovery_documents/firebasevertexai-overrides.yaml`.
- `generate_types.py` (the `swift_typegen` package) strips the Gemini
  Developer API and Gemini Enterprise Agent Platform prefixes, resolves
  the schemas reachable from the request/response roots, merges both
  backends with DocC availability callouts, checks for value-type
  cycles, renders Swift via Jinja2 templates, runs `swift-format`, and
  prunes stale generated files while preserving hand-written ones.
- Add 117 unit tests covering every pipeline stage, and `pyink` settings
  in `pyproject.toml`.
- Add a `check-data-models` CI job that runs the unit tests and warns
  when the committed data models are behind the Discovery Document.
- Add `Shared/Buildable.swift`, which the regenerated types depend on.
The `GenerateContent` sources are not regenerated here; that follows in
a separate PR.
2026-10-09 18:35:46 -04:00

93 lines
2.8 KiB
Swift

// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import Foundation
/// A type that can be initialized and populated fluently using a closure-based builder pattern.
package protocol Buildable {
/// Initializes a new instance with default values.
init()
}
extension Buildable {
/// Initializes a new instance configured by `populator`.
///
/// ```swift
/// let request = GenerateContentRequest {
/// $0.contents = [...]
/// }
/// ```
///
/// - Parameter populator: A closure that populates fields on the newly created instance.
/// - Throws: Any error thrown by `populator`.
@inlinable
package init(_ populator: (inout Self) throws -> Void) rethrows {
self.init()
try populator(&self)
}
/// Initializes a new instance asynchronously configured by `populator`.
///
/// ```swift
/// let request = await GenerateContentRequest {
/// $0.contents = [await fetchUserContent()]
/// }
/// ```
///
/// - Parameter populator: An asynchronous closure that populates fields on the newly created
/// instance.
/// - Throws: Any error thrown by `populator`.
@inlinable
package init(_ populator: (inout Self) async throws -> Void) async rethrows {
self.init()
try await populator(&self)
}
/// Returns a copy of this instance modified by `populator`.
///
/// ```swift
/// let modified = baseConfig.with {
/// $0.temperature = 0.2
/// }
/// ```
///
/// - Parameter populator: A closure that populates or updates fields on a copy of this instance.
/// - Returns: The populated copy.
/// - Throws: Any error thrown by `populator`.
@inlinable
package func with(_ populator: (inout Self) throws -> Void) rethrows -> Self {
var copy = self
try populator(&copy)
return copy
}
/// Creates a new instance, executes `populator` to populate its fields, and returns the instance.
///
/// ```swift
/// let request = GenerateContentRequest.with {
/// $0.contents = [...]
/// }
/// ```
///
/// - Parameter populator: A closure that populates fields on the newly created instance.
/// - Returns: The populated instance.
/// - Throws: Any error thrown by `populator`.
@inlinable
package static func with(_ populator: (inout Self) throws -> Void) rethrows -> Self {
var instance = Self()
try populator(&instance)
return instance
}
}