Skip to content

Commit 44ea204

Browse files
committed
[Firebase AI] Add CodeExecution tool support
1 parent 9bc71e3 commit 44ea204

File tree

5 files changed

+137
-6
lines changed

5 files changed

+137
-6
lines changed

FirebaseAI/Sources/AILog.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum AILog {
6262
case decodedInvalidCitationPublicationDate = 3011
6363
case generateContentResponseUnrecognizedContentModality = 3012
6464
case decodedUnsupportedImagenPredictionType = 3013
65+
case codeExecutionResultUnrecognizedOutcome = 3014
6566

6667
// SDK State Errors
6768
case generateContentResponseNoCandidates = 4000

FirebaseAI/Sources/Tool.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,18 @@ public struct GoogleSearch: Sendable {
7171
public struct Tool: Sendable {
7272
/// A list of `FunctionDeclarations` available to the model.
7373
let functionDeclarations: [FunctionDeclaration]?
74+
7475
/// Specifies the Google Search configuration.
7576
let googleSearch: GoogleSearch?
7677

77-
init(functionDeclarations: [FunctionDeclaration]?) {
78-
self.functionDeclarations = functionDeclarations
79-
googleSearch = nil
80-
}
78+
let codeExecution: CodeExecution?
8179

82-
init(googleSearch: GoogleSearch) {
80+
init(functionDeclarations: [FunctionDeclaration]? = nil,
81+
googleSearch: GoogleSearch? = nil,
82+
codeExecution: CodeExecution? = nil) {
83+
self.functionDeclarations = functionDeclarations
8384
self.googleSearch = googleSearch
84-
functionDeclarations = nil
85+
self.codeExecution = codeExecution
8586
}
8687

8788
/// Creates a tool that allows the model to perform function calling.
@@ -126,6 +127,10 @@ public struct Tool: Sendable {
126127
public static func googleSearch(_ googleSearch: GoogleSearch = GoogleSearch()) -> Tool {
127128
return self.init(googleSearch: googleSearch)
128129
}
130+
131+
public static func codeExecution() -> Tool {
132+
return self.init(codeExecution: CodeExecution())
133+
}
129134
}
130135

131136
/// Configuration for specifying function calling behavior.

FirebaseAI/Sources/Types/Internal/InternalPart.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,41 @@ struct FunctionResponse: Codable, Equatable, Sendable {
6363
}
6464
}
6565

66+
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
67+
struct ExecutableCode: Codable, Equatable, Sendable {
68+
let language: String
69+
let code: String
70+
71+
init(language: String, code: String) {
72+
self.language = language
73+
self.code = code
74+
}
75+
}
76+
77+
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
78+
struct CodeExecutionResult: Codable, Equatable, Sendable {
79+
struct Outcome: CodableProtoEnum, Sendable, Equatable {
80+
enum Kind: String {
81+
case ok = "OUTCOME_OK"
82+
case failed = "OUTCOME_FAILED"
83+
case deadlineExceeded = "OUTCOME_DEADLINE_EXCEEDED"
84+
}
85+
86+
let rawValue: String
87+
88+
static let unrecognizedValueMessageCode =
89+
AILog.MessageCode.codeExecutionResultUnrecognizedOutcome
90+
}
91+
92+
let outcome: Outcome
93+
let output: String?
94+
95+
init(outcome: Outcome, output: String) {
96+
self.outcome = outcome
97+
self.output = output
98+
}
99+
}
100+
66101
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
67102
struct ErrorPart: Part, Error {
68103
let error: Error

FirebaseAI/Sources/Types/Public/Part.swift

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,76 @@ public struct FunctionResponsePart: Part {
202202
self.thoughtSignature = thoughtSignature
203203
}
204204
}
205+
206+
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
207+
public struct ExecutableCodePart: Part {
208+
let executableCode: ExecutableCode
209+
let _isThought: Bool?
210+
let thoughtSignature: String?
211+
212+
public var language: String { executableCode.language }
213+
214+
public var code: String { executableCode.code }
215+
216+
public var isThought: Bool { _isThought ?? false }
217+
218+
public init(language: String, code: String) {
219+
self.init(ExecutableCode(language: language, code: code), isThought: nil, thoughtSignature: nil)
220+
}
221+
222+
init(_ executableCode: ExecutableCode, isThought: Bool?, thoughtSignature: String?) {
223+
self.executableCode = executableCode
224+
_isThought = isThought
225+
self.thoughtSignature = thoughtSignature
226+
}
227+
}
228+
229+
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
230+
public struct CodeExecutionResultPart: Part {
231+
let codeExecutionResult: CodeExecutionResult
232+
let _isThought: Bool?
233+
let thoughtSignature: String?
234+
235+
public var outcome: CodeExecutionResultPart.Outcome {
236+
CodeExecutionResultPart.Outcome(codeExecutionResult.outcome)
237+
}
238+
239+
public var output: String { codeExecutionResult.output ?? "" }
240+
241+
public var isThought: Bool { _isThought ?? false }
242+
243+
public init(outcome: CodeExecutionResultPart.Outcome, output: String) {
244+
self.init(
245+
codeExecutionResult: CodeExecutionResult(outcome: outcome.internalOutcome, output: output),
246+
_isThought: nil,
247+
thoughtSignature: nil
248+
)
249+
}
250+
251+
init(codeExecutionResult: CodeExecutionResult, _isThought: Bool?, thoughtSignature: String?) {
252+
self.codeExecutionResult = codeExecutionResult
253+
self._isThought = _isThought
254+
self.thoughtSignature = thoughtSignature
255+
}
256+
}
257+
258+
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
259+
public extension CodeExecutionResultPart {
260+
struct Outcome: Sendable, Equatable {
261+
let internalOutcome: CodeExecutionResult.Outcome
262+
263+
public static let ok = CodeExecutionResultPart.Outcome(CodeExecutionResult.Outcome(kind: .ok))
264+
265+
public static let failed =
266+
CodeExecutionResultPart.Outcome(CodeExecutionResult.Outcome(kind: .failed))
267+
268+
public static let deadlineExceeded =
269+
CodeExecutionResultPart.Outcome(CodeExecutionResult.Outcome(kind: .deadlineExceeded))
270+
271+
public var rawValue: String { internalOutcome.rawValue }
272+
273+
init(_ outcome: CodeExecutionResult.Outcome) {
274+
internalOutcome = outcome
275+
}
276+
}
277+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
public struct CodeExecution: Sendable, Encodable {
16+
init() {}
17+
}

0 commit comments

Comments
 (0)