Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<kotlin.version>2.3.21</kotlin.version>
<dokka.version>2.2.0</dokka.version>
<kotlinx-coroutines.version>1.11.0</kotlinx-coroutines.version>
<adk-kotlin.version>1.4.0</adk-kotlin.version>
<adk-kotlin.version>1.5.0</adk-kotlin.version>
<reactor-core.version>3.7.0</reactor-core.version>
<wiremock.version>2.35.1</wiremock.version>
<assertj.version>3.27.7</assertj.version>
Expand Down
3 changes: 2 additions & 1 deletion tokt/src/main/kotlin/com/google/adk/tokt/JavaAdkToKt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ object JavaAdkToKt {
* Java view of a Kotlin service is unwrapped to that Kotlin service, with no `dispatcher` hop.
* Resumption and rewinds work across the adapter if the Java service, like
* `InMemorySessionService`, returns the fields they read unchanged: `EventActions.agentState`,
* `rewindBeforeInvocationId`, and a workflow node's output, node info, and routes.
* `rewindBeforeInvocationId`, `Event.isolationScope`, and a workflow node's output, node info,
* and routes.
*/
@JvmStatic
@JvmOverloads
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import kotlin.jvm.optionals.getOrNull
* `errorCode`, `finishReason`), the token `usageMetadata` ([UsageMetadataCodec]),
* `groundingMetadata` ([GroundingMetadataCodec]) and context `cacheMetadata`
* ([CacheMetadataCodec]), a workflow node's `output` and `nodeInfo` ([WorkflowCodec]), long-running
* tool ids, and the timestamp.
* tool ids, the timestamp, and the `isolationScope`.
*/
internal object EventCodec {

Expand All @@ -49,6 +49,7 @@ internal object EventCodec {
.actions(eventActionsToJava(event.actions))
event.invocationId?.let { builder.invocationId(it) }
event.branch?.let { builder.branch(it) }
event.isolationScope?.let { builder.isolationScope(it) }
event.content?.let { builder.content(ContentCodec.toJava(it)) }
if (event.longRunningToolIds.isNotEmpty()) builder.longRunningToolIds(event.longRunningToolIds)
// Streaming/error signals are set only when meaningful, so ordinary events keep the Java
Expand Down Expand Up @@ -101,6 +102,7 @@ internal object EventCodec {
route = javaActions.route().getOrNull()?.map { WorkflowCodec.routeFromJava(it) },
),
branch = event.branch().getOrNull(),
isolationScope = event.isolationScope().getOrNull(),
partial = event.partial().getOrNull() ?: false,
turnComplete = event.turnComplete().getOrNull() ?: false,
interrupted = event.interrupted().getOrNull() ?: false,
Expand Down
15 changes: 15 additions & 0 deletions tokt/src/test/kotlin/com/google/adk/tokt/KtRunnerInteropTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4383,6 +4383,21 @@ class KtRunnerInteropTest {
assertEquals(listOf(fingerprintOnly, active), stored)
}

@Test
fun asKtSessionService_isolationScope_survivesTheJavaStore() = runBlocking {
// A task agent resumes from events in its own scope, so the scope must survive storage.
val sessions = JavaAdkToKt.asKtSessionService(JavaInMemorySessionService())
val key = KtSessionKey("app", "u", "s")
val session = sessions.createSession(key)

val unusedScoped =
sessions.appendEvent(session, KtEvent(author = "task", isolationScope = "task-1"))
val unusedUnscoped = sessions.appendEvent(session, KtEvent(author = "user"))

val stored = assertNotNull(sessions.getSession(key)).events.map { it.isolationScope }
assertEquals(listOf("task-1", null), stored)
}

@Test
fun eventCodec_workflowFields_roundTripThroughTheJavaEvent() {
// Java code reads these fields too, so a Kotlin Content in the output crosses as a genai one.
Expand Down
Loading