From 0eeb7a2ec94b9ac1c4dcb9d21200c79f63a50c71 Mon Sep 17 00:00:00 2001 From: Daymon Date: Wed, 9 Jul 2025 12:04:35 -0500 Subject: [PATCH 1/6] Add config support --- FirebaseAI/Sources/FirebaseAI.swift | 37 ++++++++--- FirebaseAI/Sources/FirebaseAIConfig.swift | 63 +++++++++++++++++++ FirebaseAI/Sources/GenerativeAIService.swift | 24 ++++++- FirebaseAI/Sources/GenerativeModel.swift | 6 +- .../Types/Public/Imagen/ImagenModel.swift | 5 +- 5 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 FirebaseAI/Sources/FirebaseAIConfig.swift diff --git a/FirebaseAI/Sources/FirebaseAI.swift b/FirebaseAI/Sources/FirebaseAI.swift index 48f7183d4e6..d7a9db704b1 100644 --- a/FirebaseAI/Sources/FirebaseAI.swift +++ b/FirebaseAI/Sources/FirebaseAI.swift @@ -32,13 +32,18 @@ public final class FirebaseAI: Sendable { /// ``FirebaseApp``. /// - backend: The backend API for the Firebase AI SDK; if not specified, uses the default /// ``Backend/googleAI()`` (Gemini Developer API). + /// - config: Configuration options for the Firebase AI SDK that propogate across all models + /// created. Uses default options when not specified, see the ``FirebaseAIConfig`` + /// documentation for more information. /// - Returns: A `FirebaseAI` instance, configured with the custom `FirebaseApp`. public static func firebaseAI(app: FirebaseApp? = nil, - backend: Backend = .googleAI()) -> FirebaseAI { + backend: Backend = .googleAI(), + config: FirebaseAIConfig = FirebaseAIConfig()) -> FirebaseAI { let instance = createInstance( app: app, location: backend.location, - apiConfig: backend.apiConfig + apiConfig: backend.apiConfig, + aiConfig: config ) // Verify that the `FirebaseAI` instance is always configured with the production endpoint since // this is the public API surface for creating an instance. @@ -90,7 +95,8 @@ public final class FirebaseAI: Sendable { tools: tools, toolConfig: toolConfig, systemInstruction: systemInstruction, - requestOptions: requestOptions + requestOptions: requestOptions, + aiConfig: aiConfig ) } @@ -126,7 +132,8 @@ public final class FirebaseAI: Sendable { apiConfig: apiConfig, generationConfig: generationConfig, safetySettings: safetySettings, - requestOptions: requestOptions + requestOptions: requestOptions, + aiConfig: aiConfig ) } @@ -141,6 +148,8 @@ public final class FirebaseAI: Sendable { let apiConfig: APIConfig + let aiConfig: FirebaseAIConfig + /// A map of active `FirebaseAI` instances keyed by the `FirebaseApp` name and the `location`, /// in the format `appName:location`. private nonisolated(unsafe) static var instances: [InstanceKey: FirebaseAI] = [:] @@ -156,7 +165,7 @@ public final class FirebaseAI: Sendable { ) static func createInstance(app: FirebaseApp?, location: String?, - apiConfig: APIConfig) -> FirebaseAI { + apiConfig: APIConfig, aiConfig: FirebaseAIConfig) -> FirebaseAI { guard let app = app ?? FirebaseApp.app() else { fatalError("No instance of the default Firebase app was found.") } @@ -166,16 +175,26 @@ public final class FirebaseAI: Sendable { // Unlock before the function returns. defer { os_unfair_lock_unlock(&instancesLock) } - let instanceKey = InstanceKey(appName: app.name, location: location, apiConfig: apiConfig) + let instanceKey = InstanceKey( + appName: app.name, + location: location, + apiConfig: apiConfig, + aiConfig: aiConfig + ) if let instance = instances[instanceKey] { return instance } - let newInstance = FirebaseAI(app: app, location: location, apiConfig: apiConfig) + let newInstance = FirebaseAI( + app: app, + location: location, + apiConfig: apiConfig, + aiConfig: aiConfig + ) instances[instanceKey] = newInstance return newInstance } - init(app: FirebaseApp, location: String?, apiConfig: APIConfig) { + init(app: FirebaseApp, location: String?, apiConfig: APIConfig, aiConfig: FirebaseAIConfig) { guard let projectID = app.options.projectID else { fatalError("The Firebase app named \"\(app.name)\" has no project ID in its configuration.") } @@ -195,6 +214,7 @@ public final class FirebaseAI: Sendable { ) self.apiConfig = apiConfig self.location = location + self.aiConfig = aiConfig } func modelResourceName(modelName: String) -> String { @@ -249,5 +269,6 @@ public final class FirebaseAI: Sendable { let appName: String let location: String? let apiConfig: APIConfig + let aiConfig: FirebaseAIConfig } } diff --git a/FirebaseAI/Sources/FirebaseAIConfig.swift b/FirebaseAI/Sources/FirebaseAIConfig.swift new file mode 100644 index 00000000000..31d2fda2f5b --- /dev/null +++ b/FirebaseAI/Sources/FirebaseAIConfig.swift @@ -0,0 +1,63 @@ +// Copyright 2025 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. + +/// Configuration options for ``FirebaseAI``, which persists across all models. +@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) +public struct FirebaseAIConfig: Sendable, Hashable, Encodable { + /// Options for App Check specific behavior within a ``FirebaseAI`` instance. + let appCheck: AppCheckOptions + + /// Creates a new ``FirebaseAI`` value. + /// + /// - Parameters: + /// - appCheck: Optionally configure certain behavior with how App Check is used. + public init(appCheck: AppCheckOptions = AppCheckOptions()) { + self.appCheck = appCheck + } +} + +/// Configurable options for how App Check is used within a ``FirebaseAI`` instance. +/// +/// Can be set when creating a ``FirebaseAIConfig``. +@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) +public struct AppCheckOptions: Sendable, Hashable, Encodable { + /// Use `limitedUseTokens`, instead of the standard cached tokens, when sending requests + /// to the backend. + let requireLimitedUseTokens: Bool + + /// Creates a new ``AppCheckOptions`` value. + /// + /// - Parameters: + /// - requiredLimitedUseTokens: When sending tokens to the backend, this option enables + /// the usage of App Check's `limitedUseTokens` instead of the standard cached tokens. + /// + /// A new `limitedUseToken` will be generated for each request; providing a lower attack + /// surface for malicious parties to hijack tokens. When used alongside [replay protection](https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection), + /// `limitedUseTokens` are also _consumed_ after each request, ensuring they can't be used + /// again. + /// + /// _To prevent breakage, this flag is set to `false` by default._ + /// + /// > Important: Replay protection is not currently supported for the FirebaseAI backend. + /// > While this feature is being developed, you can still migrate to using `limitedUseTokens`. + /// > Because `limitedUseTokens` are backwards compatable, you can still use them without replay + /// > protection. Due to their shorter TTL over standard App Check tokens, they still provide a + /// > security benefit. + /// > + /// > Migrating to `limitedUseTokens` ahead of time will also allow you to enable replay + /// > protection down the road (when support is added), without breaking your users. + public init(requiredLimitedUseTokens: Bool = false) { + requireLimitedUseTokens = requiredLimitedUseTokens + } +} diff --git a/FirebaseAI/Sources/GenerativeAIService.swift b/FirebaseAI/Sources/GenerativeAIService.swift index e1538af997f..f63f2869d4e 100644 --- a/FirebaseAI/Sources/GenerativeAIService.swift +++ b/FirebaseAI/Sources/GenerativeAIService.swift @@ -30,9 +30,12 @@ struct GenerativeAIService { private let urlSession: URLSession - init(firebaseInfo: FirebaseInfo, urlSession: URLSession) { + private let aiConfig: FirebaseAIConfig + + init(firebaseInfo: FirebaseInfo, urlSession: URLSession, aiConfig: FirebaseAIConfig) { self.firebaseInfo = firebaseInfo self.urlSession = urlSession + self.aiConfig = aiConfig } func loadRequest(request: T) async throws -> T.Response { @@ -177,7 +180,7 @@ struct GenerativeAIService { urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") if let appCheck = firebaseInfo.appCheck { - let tokenResult = await appCheck.getToken(forcingRefresh: false) + let tokenResult = await fetchAppCheckToken(appCheck: appCheck) urlRequest.setValue(tokenResult.token, forHTTPHeaderField: "X-Firebase-AppCheck") if let error = tokenResult.error { AILog.error( @@ -207,6 +210,23 @@ struct GenerativeAIService { return urlRequest } + private func fetchAppCheckToken(appCheck: AppCheckInterop) async + -> FIRAppCheckTokenResultInterop { + if aiConfig.appCheck.requireLimitedUseTokens { + if let token = await appCheck.getLimitedUseToken?() { + return token + } + + AILog.error( + code: .appCheckTokenFetchFailed, + "Missing getLimitedUseToken() function, but requireLimitedUseTokens was enabled." + ) + // falls back to standard token + } + + return await appCheck.getToken(forcingRefresh: false) + } + private func httpResponse(urlResponse: URLResponse) throws -> HTTPURLResponse { // The following condition should always be true: "Whenever you make HTTP URL load requests, any // response objects you get back from the URLSession, NSURLConnection, or NSURLDownload class diff --git a/FirebaseAI/Sources/GenerativeModel.swift b/FirebaseAI/Sources/GenerativeModel.swift index 8d3f5e043a7..8caa33bcaf7 100644 --- a/FirebaseAI/Sources/GenerativeModel.swift +++ b/FirebaseAI/Sources/GenerativeModel.swift @@ -76,6 +76,7 @@ public final class GenerativeModel: Sendable { /// only text content is supported. /// - requestOptions: Configuration parameters for sending requests to the backend. /// - urlSession: The `URLSession` to use for requests; defaults to `URLSession.shared`. + /// - aiConfig: Configuration for various behavior shared across models. init(modelName: String, modelResourceName: String, firebaseInfo: FirebaseInfo, @@ -86,13 +87,14 @@ public final class GenerativeModel: Sendable { toolConfig: ToolConfig? = nil, systemInstruction: ModelContent? = nil, requestOptions: RequestOptions, - urlSession: URLSession = GenAIURLSession.default) { + urlSession: URLSession = GenAIURLSession.default, aiConfig: FirebaseAIConfig) { self.modelName = modelName self.modelResourceName = modelResourceName self.apiConfig = apiConfig generativeAIService = GenerativeAIService( firebaseInfo: firebaseInfo, - urlSession: urlSession + urlSession: urlSession, + aiConfig: aiConfig ) self.generationConfig = generationConfig self.safetySettings = safetySettings diff --git a/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift b/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift index e6f96df511a..dca91acb3f9 100644 --- a/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift +++ b/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift @@ -53,12 +53,13 @@ public final class ImagenModel { generationConfig: ImagenGenerationConfig?, safetySettings: ImagenSafetySettings?, requestOptions: RequestOptions, - urlSession: URLSession = GenAIURLSession.default) { + urlSession: URLSession = GenAIURLSession.default, aiConfig: FirebaseAIConfig) { self.modelResourceName = modelResourceName self.apiConfig = apiConfig generativeAIService = GenerativeAIService( firebaseInfo: firebaseInfo, - urlSession: urlSession + urlSession: urlSession, + aiConfig: aiConfig ) self.generationConfig = generationConfig self.safetySettings = safetySettings From 6c878ff0559e2677a5c25ad00f6d66e51ccdee0c Mon Sep 17 00:00:00 2001 From: Daymon Date: Wed, 9 Jul 2025 12:06:19 -0500 Subject: [PATCH 2/6] fmt --- FirebaseAI/Sources/FirebaseAIConfig.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/FirebaseAI/Sources/FirebaseAIConfig.swift b/FirebaseAI/Sources/FirebaseAIConfig.swift index 31d2fda2f5b..f0f2846a121 100644 --- a/FirebaseAI/Sources/FirebaseAIConfig.swift +++ b/FirebaseAI/Sources/FirebaseAIConfig.swift @@ -50,10 +50,10 @@ public struct AppCheckOptions: Sendable, Hashable, Encodable { /// _To prevent breakage, this flag is set to `false` by default._ /// /// > Important: Replay protection is not currently supported for the FirebaseAI backend. - /// > While this feature is being developed, you can still migrate to using `limitedUseTokens`. - /// > Because `limitedUseTokens` are backwards compatable, you can still use them without replay - /// > protection. Due to their shorter TTL over standard App Check tokens, they still provide a - /// > security benefit. + /// > While this feature is being developed, you can still migrate to using + /// > `limitedUseTokens`. Because `limitedUseTokens` are backwards compatable, you can still + /// > use them without replay protection. Due to their shorter TTL over standard App Check + /// > tokens, they still provide a security benefit. /// > /// > Migrating to `limitedUseTokens` ahead of time will also allow you to enable replay /// > protection down the road (when support is added), without breaking your users. From e6de038fcef32d55c5a36631e828423c052cc33c Mon Sep 17 00:00:00 2001 From: Daymon Date: Fri, 11 Jul 2025 12:03:30 -0500 Subject: [PATCH 3/6] Migrate to nested config --- ...seAIConfig.swift => AppCheckOptions.swift} | 23 +++------------ FirebaseAI/Sources/FirebaseAI.swift | 29 ++++++++++++++----- 2 files changed, 26 insertions(+), 26 deletions(-) rename FirebaseAI/Sources/{FirebaseAIConfig.swift => AppCheckOptions.swift} (72%) diff --git a/FirebaseAI/Sources/FirebaseAIConfig.swift b/FirebaseAI/Sources/AppCheckOptions.swift similarity index 72% rename from FirebaseAI/Sources/FirebaseAIConfig.swift rename to FirebaseAI/Sources/AppCheckOptions.swift index f0f2846a121..6411eb39e12 100644 --- a/FirebaseAI/Sources/FirebaseAIConfig.swift +++ b/FirebaseAI/Sources/AppCheckOptions.swift @@ -12,24 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Configuration options for ``FirebaseAI``, which persists across all models. -@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) -public struct FirebaseAIConfig: Sendable, Hashable, Encodable { - /// Options for App Check specific behavior within a ``FirebaseAI`` instance. - let appCheck: AppCheckOptions - - /// Creates a new ``FirebaseAI`` value. - /// - /// - Parameters: - /// - appCheck: Optionally configure certain behavior with how App Check is used. - public init(appCheck: AppCheckOptions = AppCheckOptions()) { - self.appCheck = appCheck - } -} - /// Configurable options for how App Check is used within a ``FirebaseAI`` instance. /// -/// Can be set when creating a ``FirebaseAIConfig``. +/// Can be set when creating a ``FirebaseAI.Config``. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) public struct AppCheckOptions: Sendable, Hashable, Encodable { /// Use `limitedUseTokens`, instead of the standard cached tokens, when sending requests @@ -39,7 +24,7 @@ public struct AppCheckOptions: Sendable, Hashable, Encodable { /// Creates a new ``AppCheckOptions`` value. /// /// - Parameters: - /// - requiredLimitedUseTokens: When sending tokens to the backend, this option enables + /// - requireLimitedUseTokens: When sending tokens to the backend, this option enables /// the usage of App Check's `limitedUseTokens` instead of the standard cached tokens. /// /// A new `limitedUseToken` will be generated for each request; providing a lower attack @@ -57,7 +42,7 @@ public struct AppCheckOptions: Sendable, Hashable, Encodable { /// > /// > Migrating to `limitedUseTokens` ahead of time will also allow you to enable replay /// > protection down the road (when support is added), without breaking your users. - public init(requiredLimitedUseTokens: Bool = false) { - requireLimitedUseTokens = requiredLimitedUseTokens + public init(requireLimitedUseTokens: Bool = false) { + self.requireLimitedUseTokens = requireLimitedUseTokens } } diff --git a/FirebaseAI/Sources/FirebaseAI.swift b/FirebaseAI/Sources/FirebaseAI.swift index d7a9db704b1..18b2653598e 100644 --- a/FirebaseAI/Sources/FirebaseAI.swift +++ b/FirebaseAI/Sources/FirebaseAI.swift @@ -33,12 +33,12 @@ public final class FirebaseAI: Sendable { /// - backend: The backend API for the Firebase AI SDK; if not specified, uses the default /// ``Backend/googleAI()`` (Gemini Developer API). /// - config: Configuration options for the Firebase AI SDK that propogate across all models - /// created. Uses default options when not specified, see the ``FirebaseAIConfig`` + /// created. Uses default options when not specified, see the ``FirebaseAI.Config`` /// documentation for more information. /// - Returns: A `FirebaseAI` instance, configured with the custom `FirebaseApp`. public static func firebaseAI(app: FirebaseApp? = nil, backend: Backend = .googleAI(), - config: FirebaseAIConfig = FirebaseAIConfig()) -> FirebaseAI { + config: FirebaseAI.Config = .config(appCheck: AppCheckOptions())) -> FirebaseAI { let instance = createInstance( app: app, location: backend.location, @@ -140,7 +140,22 @@ public final class FirebaseAI: Sendable { /// Class to enable FirebaseAI to register via the Objective-C based Firebase component system /// to include FirebaseAI in the userAgent. @objc(FIRVertexAIComponent) class FirebaseVertexAIComponent: NSObject {} - + + /// Configuration options for ``FirebaseAI``, which persists across all models. + @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) + public struct Config : Sendable, Hashable, Encodable { + /// Options for App Check specific behavior within a ``FirebaseAI`` instance. + let appCheck: AppCheckOptions + + /// Creates a new ``FirebaseAI.Config`` value. + /// + /// - Parameters: + /// - appCheck: Optionally configure certain behavior with how App Check is used. + public static func config(appCheck: AppCheckOptions = AppCheckOptions()) -> Config { + Config(appCheck: appCheck) + } + } + // MARK: - Private /// Firebase data relevant to Firebase AI. @@ -148,7 +163,7 @@ public final class FirebaseAI: Sendable { let apiConfig: APIConfig - let aiConfig: FirebaseAIConfig + let aiConfig: FirebaseAI.Config /// A map of active `FirebaseAI` instances keyed by the `FirebaseApp` name and the `location`, /// in the format `appName:location`. @@ -165,7 +180,7 @@ public final class FirebaseAI: Sendable { ) static func createInstance(app: FirebaseApp?, location: String?, - apiConfig: APIConfig, aiConfig: FirebaseAIConfig) -> FirebaseAI { + apiConfig: APIConfig, aiConfig: FirebaseAI.Config) -> FirebaseAI { guard let app = app ?? FirebaseApp.app() else { fatalError("No instance of the default Firebase app was found.") } @@ -194,7 +209,7 @@ public final class FirebaseAI: Sendable { return newInstance } - init(app: FirebaseApp, location: String?, apiConfig: APIConfig, aiConfig: FirebaseAIConfig) { + init(app: FirebaseApp, location: String?, apiConfig: APIConfig, aiConfig: FirebaseAI.Config) { guard let projectID = app.options.projectID else { fatalError("The Firebase app named \"\(app.name)\" has no project ID in its configuration.") } @@ -269,6 +284,6 @@ public final class FirebaseAI: Sendable { let appName: String let location: String? let apiConfig: APIConfig - let aiConfig: FirebaseAIConfig + let aiConfig: FirebaseAI.Config } } From 086e673479c42ded07a895b1e0b4cccaf4fa254d Mon Sep 17 00:00:00 2001 From: Daymon Date: Fri, 11 Jul 2025 12:04:09 -0500 Subject: [PATCH 4/6] Mix invalid references --- FirebaseAI/Sources/GenerativeAIService.swift | 4 ++-- FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FirebaseAI/Sources/GenerativeAIService.swift b/FirebaseAI/Sources/GenerativeAIService.swift index f63f2869d4e..beb0fcda3c3 100644 --- a/FirebaseAI/Sources/GenerativeAIService.swift +++ b/FirebaseAI/Sources/GenerativeAIService.swift @@ -30,9 +30,9 @@ struct GenerativeAIService { private let urlSession: URLSession - private let aiConfig: FirebaseAIConfig + private let aiConfig: FirebaseAI.Config - init(firebaseInfo: FirebaseInfo, urlSession: URLSession, aiConfig: FirebaseAIConfig) { + init(firebaseInfo: FirebaseInfo, urlSession: URLSession, aiConfig: FirebaseAI.Config) { self.firebaseInfo = firebaseInfo self.urlSession = urlSession self.aiConfig = aiConfig diff --git a/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift b/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift index dca91acb3f9..254e1fe21ea 100644 --- a/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift +++ b/FirebaseAI/Sources/Types/Public/Imagen/ImagenModel.swift @@ -53,7 +53,7 @@ public final class ImagenModel { generationConfig: ImagenGenerationConfig?, safetySettings: ImagenSafetySettings?, requestOptions: RequestOptions, - urlSession: URLSession = GenAIURLSession.default, aiConfig: FirebaseAIConfig) { + urlSession: URLSession = GenAIURLSession.default, aiConfig: FirebaseAI.Config) { self.modelResourceName = modelResourceName self.apiConfig = apiConfig generativeAIService = GenerativeAIService( From 4c9d28b47c9de8c84a0528f5919a066581565c27 Mon Sep 17 00:00:00 2001 From: Daymon Date: Fri, 11 Jul 2025 12:04:38 -0500 Subject: [PATCH 5/6] Fix invalid reference (again) --- FirebaseAI/Sources/GenerativeModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FirebaseAI/Sources/GenerativeModel.swift b/FirebaseAI/Sources/GenerativeModel.swift index 8caa33bcaf7..0a229d3489c 100644 --- a/FirebaseAI/Sources/GenerativeModel.swift +++ b/FirebaseAI/Sources/GenerativeModel.swift @@ -87,7 +87,7 @@ public final class GenerativeModel: Sendable { toolConfig: ToolConfig? = nil, systemInstruction: ModelContent? = nil, requestOptions: RequestOptions, - urlSession: URLSession = GenAIURLSession.default, aiConfig: FirebaseAIConfig) { + urlSession: URLSession = GenAIURLSession.default, aiConfig: FirebaseAI.Config) { self.modelName = modelName self.modelResourceName = modelResourceName self.apiConfig = apiConfig From 8a06ee5d9a834bc44914c49ca43ca3cfedeebeba Mon Sep 17 00:00:00 2001 From: Daymon Date: Fri, 11 Jul 2025 12:06:51 -0500 Subject: [PATCH 6/6] fmt --- FirebaseAI/Sources/FirebaseAI.swift | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/FirebaseAI/Sources/FirebaseAI.swift b/FirebaseAI/Sources/FirebaseAI.swift index 18b2653598e..b9938ced25b 100644 --- a/FirebaseAI/Sources/FirebaseAI.swift +++ b/FirebaseAI/Sources/FirebaseAI.swift @@ -38,7 +38,8 @@ public final class FirebaseAI: Sendable { /// - Returns: A `FirebaseAI` instance, configured with the custom `FirebaseApp`. public static func firebaseAI(app: FirebaseApp? = nil, backend: Backend = .googleAI(), - config: FirebaseAI.Config = .config(appCheck: AppCheckOptions())) -> FirebaseAI { + config: FirebaseAI + .Config = .config(appCheck: AppCheckOptions())) -> FirebaseAI { let instance = createInstance( app: app, location: backend.location, @@ -140,13 +141,13 @@ public final class FirebaseAI: Sendable { /// Class to enable FirebaseAI to register via the Objective-C based Firebase component system /// to include FirebaseAI in the userAgent. @objc(FIRVertexAIComponent) class FirebaseVertexAIComponent: NSObject {} - + /// Configuration options for ``FirebaseAI``, which persists across all models. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) - public struct Config : Sendable, Hashable, Encodable { + public struct Config: Sendable, Hashable, Encodable { /// Options for App Check specific behavior within a ``FirebaseAI`` instance. let appCheck: AppCheckOptions - + /// Creates a new ``FirebaseAI.Config`` value. /// /// - Parameters: @@ -155,7 +156,7 @@ public final class FirebaseAI: Sendable { Config(appCheck: appCheck) } } - + // MARK: - Private /// Firebase data relevant to Firebase AI.