@@ -49,7 +49,9 @@ async def add_session_event_async(self, **kwargs):
4949
5050 async def get_session_memory_async (self , * , session_id ):
5151 if self .get_response is None :
52- raise RuntimeError ("not found" )
52+ error = RuntimeError ("not found" )
53+ error .status_code = 404 # type: ignore[attr-defined]
54+ raise error
5355 return self .get_response
5456
5557 async def delete_session_memory_async (self , * , session_id ):
@@ -154,20 +156,36 @@ def service(self, fake_client):
154156 with patch .object (service , "_get_client" , return_value = fake_client ):
155157 yield service
156158
157- def test_storage_session_id_round_trips (self , service ):
158- """Test storage session IDs preserve ADK scope ."""
159+ def test_storage_session_id_uses_managed_safe_hex (self , service ):
160+ """Test managed storage session IDs fit API charset and length limits ."""
159161 storage_id = service ._storage_session_id (
160162 app_name = "app" ,
161163 user_id = "alice" ,
162164 session_id = "session-1" ,
163165 )
164166
165- assert service ._parse_storage_session_id (storage_id ) == (
166- "test_ns" ,
167- "alice" ,
168- "session-1" ,
167+ assert len (storage_id ) == 64
168+ assert storage_id .isalnum ()
169+ assert (
170+ service ._storage_session_id (
171+ app_name = "app" ,
172+ user_id = "alice" ,
173+ session_id = "session-1" ,
174+ )
175+ == storage_id
169176 )
170177
178+ def test_storage_session_id_hashes_uuid_session_ids (self , service ):
179+ """Test ADK UUID session IDs map to deterministic managed storage IDs."""
180+ storage_id = service ._storage_session_id (
181+ app_name = "app" ,
182+ user_id = "user" ,
183+ session_id = "28a7d6e2-0f0f-43b6-b22c-47e03635ed34" ,
184+ )
185+
186+ assert len (storage_id ) == 64
187+ assert storage_id .isalnum ()
188+
171189 @pytest .mark .asyncio
172190 async def test_append_event_writes_session_event (self , service , fake_client ):
173191 """Test append_event stores a Redis Agent Memory session event."""
@@ -193,9 +211,24 @@ async def test_append_event_writes_session_event(self, service, fake_client):
193211 stored = fake_client .added_events [0 ]
194212 assert stored ["actor_id" ] == "alice"
195213 assert stored ["content" ] == [{"text" : "I prefer window seats." }]
196- assert stored ["metadata" ]["namespace" ] == "test_ns "
214+ assert stored ["metadata" ]["namespace" ] == "test-ns "
197215 assert stored ["metadata" ]["adk_event_id" ] == "event-1"
198216
217+ @pytest .mark .asyncio
218+ async def test_get_session_returns_empty_before_first_event (
219+ self , service , fake_client
220+ ):
221+ """Test get_session returns an empty session before Redis materializes it."""
222+ session = await service .get_session (
223+ app_name = "app" ,
224+ user_id = "alice" ,
225+ session_id = "fa58803d-9a11-4466-8f3f-40baf61b41c0" ,
226+ )
227+
228+ assert session is not None
229+ assert session .id == "fa58803d-9a11-4466-8f3f-40baf61b41c0"
230+ assert session .events == []
231+
199232 @pytest .mark .asyncio
200233 async def test_get_session_reconstructs_adk_events (
201234 self , service , fake_client
@@ -237,6 +270,40 @@ async def test_get_session_reconstructs_adk_events(
237270 assert session .events [0 ].id == "event-1"
238271 assert session .events [0 ].content .parts [0 ].text == "I prefer window seats."
239272
273+ @pytest .mark .asyncio
274+ async def test_list_sessions_resolves_storage_ids_from_metadata (
275+ self , service , fake_client
276+ ):
277+ """Test list_sessions resolves managed storage IDs from event metadata."""
278+ storage_id = service ._storage_session_id (
279+ app_name = "app" ,
280+ user_id = "alice" ,
281+ session_id = "28a7d6e2-0f0f-43b6-b22c-47e03635ed34" ,
282+ )
283+ fake_client .get_response = SimpleNamespace (
284+ session_id = storage_id ,
285+ owner_id = "alice" ,
286+ events = [
287+ SimpleNamespace (
288+ metadata = {
289+ "namespace" : "test-ns" ,
290+ "user_id" : "alice" ,
291+ "adk_session_id" : "28a7d6e2-0f0f-43b6-b22c-47e03635ed34" ,
292+ }
293+ )
294+ ],
295+ )
296+ fake_client .list_response = SimpleNamespace (
297+ items = [storage_id ],
298+ next_page_token = None ,
299+ )
300+
301+ response = await service .list_sessions (app_name = "app" , user_id = "alice" )
302+
303+ assert [session .id for session in response .sessions ] == [
304+ "28a7d6e2-0f0f-43b6-b22c-47e03635ed34"
305+ ]
306+
240307 @pytest .mark .asyncio
241308 async def test_list_sessions_filters_internal_ids (self , service , fake_client ):
242309 """Test list_sessions filters by namespace and user."""
@@ -245,14 +312,31 @@ async def test_list_sessions_filters_internal_ids(self, service, fake_client):
245312 user_id = "alice" ,
246313 session_id = "session-1" ,
247314 )
315+ fake_client .get_response = SimpleNamespace (
316+ session_id = storage_id ,
317+ owner_id = "alice" ,
318+ events = [
319+ SimpleNamespace (
320+ metadata = {
321+ "namespace" : "test-ns" ,
322+ "user_id" : "alice" ,
323+ "adk_session_id" : "session-1" ,
324+ }
325+ )
326+ ],
327+ )
248328 fake_client .list_response = SimpleNamespace (
249- items = [storage_id , "external-session" ],
329+ items = [storage_id ],
250330 next_page_token = None ,
251331 )
252332
253333 response = await service .list_sessions (app_name = "app" , user_id = "alice" )
254334
255335 assert [session .id for session in response .sessions ] == ["session-1" ]
336+ response_other_user = await service .list_sessions (
337+ app_name = "app" , user_id = "bob"
338+ )
339+ assert response_other_user .sessions == []
256340
257341 @pytest .mark .asyncio
258342 async def test_close_completes_without_error (self , service ):
0 commit comments