diff --git a/tokt/src/main/kotlin/com/google/adk/tokt/codecs/GroundingMetadataCodec.kt b/tokt/src/main/kotlin/com/google/adk/tokt/codecs/GroundingMetadataCodec.kt index d0c1bf80a..65300b6cb 100644 --- a/tokt/src/main/kotlin/com/google/adk/tokt/codecs/GroundingMetadataCodec.kt +++ b/tokt/src/main/kotlin/com/google/adk/tokt/codecs/GroundingMetadataCodec.kt @@ -49,7 +49,7 @@ internal object GroundingMetadataCodec { /** Returns the Kotlin [KtGroundingMetadata] view of the genai [metadata]. */ fun fromJava(metadata: GenaiGroundingMetadata): KtGroundingMetadata = KtGroundingMetadata( - imageSearchQueries = metadata.imageSearchQueries().getOrNull().orEmpty(), + imageSearchQueries = metadata.imageSearchQueries().getOrNull(), groundingChunks = metadata.groundingChunks().getOrNull()?.map { chunkFromJava(it) }, groundingSupports = metadata.groundingSupports().getOrNull()?.map { supportFromJava(it) }, webSearchQueries = metadata.webSearchQueries().getOrNull(), @@ -62,7 +62,8 @@ internal object GroundingMetadataCodec { /** Returns the genai [GenaiGroundingMetadata] view of the Kotlin [metadata]. */ fun toJava(metadata: KtGroundingMetadata): GenaiGroundingMetadata { - val builder = GenaiGroundingMetadata.builder().imageSearchQueries(metadata.imageSearchQueries) + val builder = GenaiGroundingMetadata.builder() + metadata.imageSearchQueries?.let { builder.imageSearchQueries(it) } metadata.groundingChunks?.let { builder.groundingChunks(it.map { c -> chunkToJava(c) }) } metadata.groundingSupports?.let { builder.groundingSupports(it.map { s -> supportToJava(s) }) } metadata.webSearchQueries?.let { builder.webSearchQueries(it) } diff --git a/tokt/src/test/kotlin/com/google/adk/tokt/KtRunnerInteropTest.kt b/tokt/src/test/kotlin/com/google/adk/tokt/KtRunnerInteropTest.kt index 3db6e912d..dd48ff0f0 100644 --- a/tokt/src/test/kotlin/com/google/adk/tokt/KtRunnerInteropTest.kt +++ b/tokt/src/test/kotlin/com/google/adk/tokt/KtRunnerInteropTest.kt @@ -64,6 +64,7 @@ import com.google.adk.kt.types.GenerationConfigRoutingConfig as KtRoutingConfig import com.google.adk.kt.types.GenerationConfigRoutingConfigManualRoutingMode as KtManualRoutingMode import com.google.adk.kt.types.GoogleMaps as KtGoogleMaps import com.google.adk.kt.types.GoogleSearch as KtGoogleSearch +import com.google.adk.kt.types.GroundingMetadata as KtGroundingMetadata import com.google.adk.kt.types.HarmBlockMethod as KtHarmBlockMethod import com.google.adk.kt.types.HarmBlockThreshold as KtHarmBlockThreshold import com.google.adk.kt.types.HarmCategory as KtHarmCategory @@ -4552,6 +4553,24 @@ class KtRunnerInteropTest { assertEquals("places/abc", maps.placeId().getOrNull(), "maps chunk placeId") } + @Test + fun asKtSessionService_groundingMetadata_survivesTheJavaStore() = runBlocking { + // Kotlin's Gemini leaves imageSearchQueries unset on a Google Search answer. + val sessions = JavaAdkToKt.asKtSessionService(JavaInMemorySessionService()) + val key = KtSessionKey("app", "u", "s") + val session = sessions.createSession(key) + val webSearch = KtGroundingMetadata(webSearchQueries = listOf("tallest building")) + val imageSearch = KtGroundingMetadata(imageSearchQueries = listOf("cat")) + + for (grounding in listOf(webSearch, imageSearch)) { + val unused = + sessions.appendEvent(session, KtEvent(author = "model", groundingMetadata = grounding)) + } + + val stored = assertNotNull(sessions.getSession(key)).events.map { it.groundingMetadata } + assertEquals(listOf(webSearch, imageSearch), stored) + } + @Test fun asKtSessionService_listEvents_carriesNextPageToken() = runBlocking { // The listEvents bridge must carry nextPageToken, or a paged Java service's continuation token