From 90857d619993cb4ca0246806ffc3565deeb00c75 Mon Sep 17 00:00:00 2001 From: Andrew Heard Date: Thu, 31 Jul 2025 19:01:20 -0400 Subject: [PATCH 1/2] [Firebase AI] Add `id` property to `FunctionResponsePart` --- FirebaseAI/Sources/Types/Internal/InternalPart.swift | 9 +++++++-- FirebaseAI/Sources/Types/Public/Part.swift | 12 +++++++++--- .../Unit/Snippets/FunctionCallingSnippets.swift | 1 + 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/FirebaseAI/Sources/Types/Internal/InternalPart.swift b/FirebaseAI/Sources/Types/Internal/InternalPart.swift index d543fb80f38..ce090b426a8 100644 --- a/FirebaseAI/Sources/Types/Internal/InternalPart.swift +++ b/FirebaseAI/Sources/Types/Internal/InternalPart.swift @@ -44,10 +44,12 @@ struct FileData: Codable, Equatable, Sendable { @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) struct FunctionCall: Equatable, Sendable { let name: String + let id: String? let args: JSONObject - init(name: String, args: JSONObject) { + init(name: String, id: String?, args: JSONObject) { self.name = name + self.id = id self.args = args } } @@ -55,10 +57,12 @@ struct FunctionCall: Equatable, Sendable { @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) struct FunctionResponse: Codable, Equatable, Sendable { let name: String + let id: String? let response: JSONObject - init(name: String, response: JSONObject) { + init(name: String, id: String?, response: JSONObject) { self.name = name + self.id = id self.response = response } } @@ -79,6 +83,7 @@ extension FunctionCall: Codable { init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) name = try container.decode(String.self, forKey: .name) + id = try container.decodeIfPresent(String.self, forKey: .id) if let args = try container.decodeIfPresent(JSONObject.self, forKey: .args) { self.args = args } else { diff --git a/FirebaseAI/Sources/Types/Public/Part.swift b/FirebaseAI/Sources/Types/Public/Part.swift index 4890b725f4d..3f373a48595 100644 --- a/FirebaseAI/Sources/Types/Public/Part.swift +++ b/FirebaseAI/Sources/Types/Public/Part.swift @@ -109,6 +109,10 @@ public struct FunctionCallPart: Part { /// The name of the function to call. public var name: String { functionCall.name } + /// The unique ID of the function call. If specified, this identifier should be included in the + /// ``FunctionResponsePart``. + public var id: String? { functionCall.id } + /// The function parameters and values. public var args: JSONObject { functionCall.args } @@ -121,7 +125,7 @@ public struct FunctionCallPart: Part { /// - name: The name of the function to call. /// - args: The function parameters and values. public init(name: String, args: JSONObject) { - self.init(FunctionCall(name: name, args: args)) + self.init(FunctionCall(name: name, id: nil, args: args)) } init(_ functionCall: FunctionCall) { @@ -148,9 +152,11 @@ public struct FunctionResponsePart: Part { /// /// - Parameters: /// - name: The name of the function that was called. + /// - id: The unique ID of the function call, if specified, that this response corresponds with; + /// see ``FunctionCallPart/id`` for more details. /// - response: The function's response. - public init(name: String, response: JSONObject) { - self.init(FunctionResponse(name: name, response: response)) + public init(name: String, id: String? = nil, response: JSONObject) { + self.init(FunctionResponse(name: name, id: id, response: response)) } init(_ functionResponse: FunctionResponse) { diff --git a/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift b/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift index e8ef9bf512c..5c2ed12b2a2 100644 --- a/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift +++ b/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift @@ -92,6 +92,7 @@ final class FunctionCallingSnippets: XCTestCase { functionResponses.append(FunctionResponsePart( name: functionCall.name, + id: functionCall.id, response: fetchWeather(city: city, state: state, date: date) )) } From 61e5960a8cc1a54fd3120fc37a05a31381451ac1 Mon Sep 17 00:00:00 2001 From: Andrew Heard Date: Thu, 31 Jul 2025 19:59:18 -0400 Subject: [PATCH 2/2] Re-ordered parameters to align with the Android SDK --- .../Sources/Types/Internal/InternalPart.swift | 12 ++++++------ FirebaseAI/Sources/Types/Public/Part.swift | 14 +++++++------- .../Unit/Snippets/FunctionCallingSnippets.swift | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/FirebaseAI/Sources/Types/Internal/InternalPart.swift b/FirebaseAI/Sources/Types/Internal/InternalPart.swift index ce090b426a8..5a655062729 100644 --- a/FirebaseAI/Sources/Types/Internal/InternalPart.swift +++ b/FirebaseAI/Sources/Types/Internal/InternalPart.swift @@ -44,26 +44,26 @@ struct FileData: Codable, Equatable, Sendable { @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) struct FunctionCall: Equatable, Sendable { let name: String - let id: String? let args: JSONObject + let id: String? - init(name: String, id: String?, args: JSONObject) { + init(name: String, args: JSONObject, id: String?) { self.name = name - self.id = id self.args = args + self.id = id } } @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) struct FunctionResponse: Codable, Equatable, Sendable { let name: String - let id: String? let response: JSONObject + let id: String? - init(name: String, id: String?, response: JSONObject) { + init(name: String, response: JSONObject, id: String?) { self.name = name - self.id = id self.response = response + self.id = id } } diff --git a/FirebaseAI/Sources/Types/Public/Part.swift b/FirebaseAI/Sources/Types/Public/Part.swift index 3f373a48595..1ec790f337d 100644 --- a/FirebaseAI/Sources/Types/Public/Part.swift +++ b/FirebaseAI/Sources/Types/Public/Part.swift @@ -109,13 +109,13 @@ public struct FunctionCallPart: Part { /// The name of the function to call. public var name: String { functionCall.name } + /// The function parameters and values. + public var args: JSONObject { functionCall.args } + /// The unique ID of the function call. If specified, this identifier should be included in the /// ``FunctionResponsePart``. public var id: String? { functionCall.id } - /// The function parameters and values. - public var args: JSONObject { functionCall.args } - /// Constructs a new function call part. /// /// > Note: A `FunctionCallPart` is typically received from the model, rather than created @@ -125,7 +125,7 @@ public struct FunctionCallPart: Part { /// - name: The name of the function to call. /// - args: The function parameters and values. public init(name: String, args: JSONObject) { - self.init(FunctionCall(name: name, id: nil, args: args)) + self.init(FunctionCall(name: name, args: args, id: nil)) } init(_ functionCall: FunctionCall) { @@ -152,11 +152,11 @@ public struct FunctionResponsePart: Part { /// /// - Parameters: /// - name: The name of the function that was called. + /// - response: The function's response. /// - id: The unique ID of the function call, if specified, that this response corresponds with; /// see ``FunctionCallPart/id`` for more details. - /// - response: The function's response. - public init(name: String, id: String? = nil, response: JSONObject) { - self.init(FunctionResponse(name: name, id: id, response: response)) + public init(name: String, response: JSONObject, id: String? = nil) { + self.init(FunctionResponse(name: name, response: response, id: id)) } init(_ functionResponse: FunctionResponse) { diff --git a/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift b/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift index 5c2ed12b2a2..e3264cc4e00 100644 --- a/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift +++ b/FirebaseAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift @@ -92,8 +92,8 @@ final class FunctionCallingSnippets: XCTestCase { functionResponses.append(FunctionResponsePart( name: functionCall.name, - id: functionCall.id, - response: fetchWeather(city: city, state: state, date: date) + response: fetchWeather(city: city, state: state, date: date), + id: functionCall.id )) } // TODO(developer): Handle other potential function calls, if any.