Skip to content

Commit 6da9e18

Browse files
google-genai-botcopybara-github
authored andcommitted
fix: Align InMemorySessionService listSessions with Python implementation
The Java implementation of listSessions now mirrors the Python implementation: it returns session copies that include merged app-level and user-level state, and it clears the events list before returning the sessions. This ensures behavioral consistency between the Java and Python in-memory session services. Tests have been updated to reflect this change. PiperOrigin-RevId: 847975769
1 parent 9611f89 commit 6da9e18

2 files changed

Lines changed: 23 additions & 23 deletions

File tree

core/src/main/java/com/google/adk/sessions/InMemorySessionService.java

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535
import java.util.concurrent.ConcurrentHashMap;
3636
import java.util.concurrent.ConcurrentMap;
3737
import org.jspecify.annotations.Nullable;
38-
import org.slf4j.Logger;
39-
import org.slf4j.LoggerFactory;
4038

4139
/**
4240
* An in-memory implementation of {@link BaseSessionService} assuming {@link Session} objects are
@@ -50,9 +48,6 @@
5048
* during retrieval operations ({@code getSession}, {@code createSession}).
5149
*/
5250
public final class InMemorySessionService implements BaseSessionService {
53-
54-
private static final Logger logger = LoggerFactory.getLogger(InMemorySessionService.class);
55-
5651
// Structure: appName -> userId -> sessionId -> Session
5752
private final ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<String, Session>>>
5853
sessions;
@@ -179,7 +174,9 @@ public Single<ListSessionsResponse> listSessions(String appName, String userId)
179174
// Create copies with empty events and state for the response
180175
List<Session> sessionCopies =
181176
userSessionsMap.values().stream()
182-
.map(this::copySessionMetadata)
177+
.map(this::copySession)
178+
.peek(s -> s.events().clear())
179+
.map(s -> mergeWithGlobalState(appName, userId, s))
183180
.collect(toCollection(ArrayList::new));
184181

185182
return Single.just(ListSessionsResponse.builder().sessions(sessionCopies).build());
@@ -298,21 +295,6 @@ private Session copySession(Session original) {
298295
.build();
299296
}
300297

301-
/**
302-
* Creates a copy of the session containing only metadata fields (ID, appName, userId, timestamp).
303-
* State and Events are explicitly *not* copied.
304-
*
305-
* @param original The session whose metadata to copy.
306-
* @return A new Session instance with only metadata fields populated.
307-
*/
308-
private Session copySessionMetadata(Session original) {
309-
return Session.builder(original.id())
310-
.appName(original.appName())
311-
.userId(original.userId())
312-
.lastUpdateTime(original.lastUpdateTime())
313-
.build();
314-
}
315-
316298
/**
317299
* Merges the app-specific and user-specific state into the provided *mutable* session's state
318300
* map.

core/src/test/java/com/google/adk/sessions/InMemorySessionServiceTest.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,31 @@ public void lifecycle_getSession() {
8282
public void lifecycle_listSessions() {
8383
InMemorySessionService sessionService = new InMemorySessionService();
8484

85-
Session session = sessionService.createSession("app-name", "user-id").blockingGet();
85+
Session session =
86+
sessionService
87+
.createSession("app-name", "user-id", new ConcurrentHashMap<>(), "session-1")
88+
.blockingGet();
89+
90+
ConcurrentMap<String, Object> stateDelta = new ConcurrentHashMap<>();
91+
stateDelta.put("sessionKey", "sessionValue");
92+
stateDelta.put("_app_appKey", "appValue");
93+
stateDelta.put("_user_userKey", "userValue");
94+
95+
Event event =
96+
Event.builder().actions(EventActions.builder().stateDelta(stateDelta).build()).build();
97+
98+
var unused = sessionService.appendEvent(session, event).blockingGet();
8699

87100
ListSessionsResponse response =
88101
sessionService.listSessions(session.appName(), session.userId()).blockingGet();
102+
Session listedSession = response.sessions().get(0);
89103

90104
assertThat(response.sessions()).hasSize(1);
91-
assertThat(response.sessions().get(0).id()).isEqualTo(session.id());
105+
assertThat(listedSession.id()).isEqualTo(session.id());
106+
assertThat(listedSession.events()).isEmpty();
107+
assertThat(listedSession.state()).containsEntry("sessionKey", "sessionValue");
108+
assertThat(listedSession.state()).containsEntry("_app_appKey", "appValue");
109+
assertThat(listedSession.state()).containsEntry("_user_userKey", "userValue");
92110
}
93111

94112
@Test

0 commit comments

Comments
 (0)