From 0e7a4e8771cb70abab3b90415bf317ef5b02dc19 Mon Sep 17 00:00:00 2001 From: VinayGuthal Date: Thu, 31 Jul 2025 20:25:01 -0400 Subject: [PATCH 1/3] fix function calling issue --- .../firebase/ai/type/LiveServerMessage.kt | 3 +- .../google/firebase/ai/type/LiveSession.kt | 9 ++-- .../com/google/firebase/ai/type/Part.kt | 41 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveServerMessage.kt b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveServerMessage.kt index 3e3e90636e5..5cabe593bd6 100644 --- a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveServerMessage.kt +++ b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveServerMessage.kt @@ -135,7 +135,8 @@ public class LiveServerToolCall(public val functionCalls: List toolCall.functionCalls.map { functionCall -> FunctionCallPart( name = functionCall.name, - args = functionCall.args.orEmpty().mapValues { it.value ?: JsonNull } + args = functionCall.args.orEmpty().mapValues { it.value ?: JsonNull }, + id = functionCall.id ) } ) diff --git a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt index 1f84c18a53b..c4d52ab87ca 100644 --- a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt +++ b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt @@ -152,16 +152,14 @@ internal constructor( while (true) { val response = session.incoming.tryReceive() if (response.isClosed || !startedReceiving.get()) break - response .getOrNull() ?.let { - JSON.decodeFromString( - it.readBytes().toString(Charsets.UTF_8) - ) + val output = it.readBytes().toString(Charsets.UTF_8) + println(output) + JSON.decodeFromString(output) } ?.let { emit(it.toPublic()) } - yield() } } @@ -213,6 +211,7 @@ internal constructor( BidiGenerateContentToolResponseSetup(functionList.map { it.toInternalFunctionCall() }) .toInternal() ) + println(jsonString) session.send(Frame.Text(jsonString)) } } diff --git a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Part.kt b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Part.kt index bcc7e14b657..5f3e1bc12a9 100644 --- a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Part.kt +++ b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Part.kt @@ -39,6 +39,35 @@ public class TextPart(public val text: String) : Part { @Serializable internal data class Internal(val text: String) : InternalPart } +public class CodeExecutionResultPart(public val outcome: String, public val output: String) : Part { + + @Serializable + internal data class Internal( + @SerialName("codeExecutionResult") val codeExecutionResult: CodeExecutionResult + ) : InternalPart { + + @Serializable + internal data class CodeExecutionResult( + @SerialName("outcome") val outcome: String, + val output: String + ) + } +} + +public class ExecutableCodePart(public val language: String, public val code: String) : Part { + + @Serializable + internal data class Internal(@SerialName("executableCode") val executableCode: ExecutableCode) : + InternalPart { + + @Serializable + internal data class ExecutableCode( + @SerialName("language") val language: String, + val code: String + ) + } +} + /** * Represents image data sent to and received from requests. The image is converted client-side to * JPEG encoding at 80% quality before being sent to the server. @@ -176,6 +205,8 @@ internal object PartSerializer : val jsonObject = element.jsonObject return when { "text" in jsonObject -> TextPart.Internal.serializer() + "executableCode" in jsonObject -> ExecutableCodePart.Internal.serializer() + "codeExecutionResult" in jsonObject -> CodeExecutionResultPart.Internal.serializer() "functionCall" in jsonObject -> FunctionCallPart.Internal.serializer() "functionResponse" in jsonObject -> FunctionResponsePart.Internal.serializer() "inlineData" in jsonObject -> InlineDataPart.Internal.serializer() @@ -207,6 +238,12 @@ internal fun Part.toInternal(): InternalPart { ) is FileDataPart -> FileDataPart.Internal(FileDataPart.Internal.FileData(mimeType = mimeType, fileUri = uri)) + is ExecutableCodePart -> + ExecutableCodePart.Internal(ExecutableCodePart.Internal.ExecutableCode(language, code)) + is CodeExecutionResultPart -> + CodeExecutionResultPart.Internal( + CodeExecutionResultPart.Internal.CodeExecutionResult(outcome, output) + ) else -> throw com.google.firebase.ai.type.SerializationException( "The given subclass of Part (${javaClass.simpleName}) is not supported in the serialization yet." @@ -241,6 +278,10 @@ internal fun InternalPart.toPublic(): Part { is FunctionResponsePart.Internal -> FunctionResponsePart(functionResponse.name, functionResponse.response, functionResponse.id) is FileDataPart.Internal -> FileDataPart(fileData.mimeType, fileData.fileUri) + is ExecutableCodePart.Internal -> + ExecutableCodePart(executableCode.language, executableCode.code) + is CodeExecutionResultPart.Internal -> + CodeExecutionResultPart(codeExecutionResult.outcome, codeExecutionResult.output) else -> throw com.google.firebase.ai.type.SerializationException( "Unsupported part type \"${javaClass.simpleName}\" provided. This model may not be supported by this SDK." From 22da043d56e6bf6c2f0c529dec45c6ba2c92d030 Mon Sep 17 00:00:00 2001 From: VinayGuthal Date: Thu, 31 Jul 2025 20:26:46 -0400 Subject: [PATCH 2/3] fix typo --- .../main/kotlin/com/google/firebase/ai/type/LiveSession.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt index c4d52ab87ca..6e584fe2a50 100644 --- a/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt +++ b/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/LiveSession.kt @@ -155,9 +155,9 @@ internal constructor( response .getOrNull() ?.let { - val output = it.readBytes().toString(Charsets.UTF_8) - println(output) - JSON.decodeFromString(output) + JSON.decodeFromString( + it.readBytes().toString(Charsets.UTF_8) + ) } ?.let { emit(it.toPublic()) } yield() @@ -211,7 +211,6 @@ internal constructor( BidiGenerateContentToolResponseSetup(functionList.map { it.toInternalFunctionCall() }) .toInternal() ) - println(jsonString) session.send(Frame.Text(jsonString)) } } From 675b839915bca8238054e4f46d311fc9c4e2e65f Mon Sep 17 00:00:00 2001 From: VinayGuthal Date: Thu, 31 Jul 2025 20:45:20 -0400 Subject: [PATCH 3/3] update api text --- firebase-ai/api.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/firebase-ai/api.txt b/firebase-ai/api.txt index b979c361b52..43ee5243d6a 100644 --- a/firebase-ai/api.txt +++ b/firebase-ai/api.txt @@ -210,6 +210,14 @@ package com.google.firebase.ai.type { property public final java.util.List citations; } + public final class CodeExecutionResultPart implements com.google.firebase.ai.type.Part { + ctor public CodeExecutionResultPart(String outcome, String output); + method public String getOutcome(); + method public String getOutput(); + property public final String outcome; + property public final String output; + } + public final class Content { ctor public Content(String? role = "user", java.util.List parts); ctor public Content(java.util.List parts); @@ -277,6 +285,14 @@ package com.google.firebase.ai.type { property public final int width; } + public final class ExecutableCodePart implements com.google.firebase.ai.type.Part { + ctor public ExecutableCodePart(String language, String code); + method public String getCode(); + method public String getLanguage(); + property public final String code; + property public final String language; + } + public final class FileDataPart implements com.google.firebase.ai.type.Part { ctor public FileDataPart(String uri, String mimeType); method public String getMimeType();