Skip to content
Open
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
5 changes: 4 additions & 1 deletion src/google/adk/sessions/vertex_ai_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,10 +551,13 @@ def _from_api_event(api_event_obj: vertexai.types.SessionEvent) -> Event:
event_dict = copy.deepcopy(raw_event_dict)
timestamp_obj = getattr(api_event_obj, 'timestamp', None)
event_dict.update({
'id': api_event_obj.name.split('/')[-1],
'invocation_id': getattr(api_event_obj, 'invocation_id', None),
'author': getattr(api_event_obj, 'author', None),
})
# Preserve the original ADK event id from raw_event so it stays stable
# across streaming and reload; only fall back to the Vertex resource
# name if raw_event lacks an id (older data).
event_dict.setdefault('id', api_event_obj.name.split('/')[-1])
if timestamp_obj:
event_dict['timestamp'] = timestamp_obj.timestamp()
return Event.model_validate(event_dict)
Expand Down
45 changes: 45 additions & 0 deletions tests/unittests/sessions/test_vertex_ai_session_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,24 @@ def _generate_mock_events_for_session_5(num_events):
},
}]

MOCK_EVENT_WITH_RAW_EVENT_ID_JSON = [{
'name': (
'projects/test-project/locations/test-location/'
'reasoningEngines/123/sessions/override/events/658731057016733696'
),
'invocationId': 'e-1',
'author': 'user_with_override',
'timestamp': '2024-12-12T12:12:12.123456Z',
'content': {},
'actions': {},
'rawEvent': {
'id': 'c452feb0-b9ad-48b1-b863-c7dd2f085378',
'invocationId': 'e-1',
'author': 'user_with_override',
'content': {},
},
}]

MOCK_SESSION_WITH_OVERRIDE_JSON = {
'name': (
'projects/test-project/locations/test-location/'
Expand Down Expand Up @@ -853,6 +871,33 @@ async def test_get_session_from_raw_event(
assert event.error_message == 'raw_event_error'


@pytest.mark.asyncio
@pytest.mark.usefixtures('mock_get_api_client')
async def test_get_session_preserves_original_event_id_from_raw_event(
mock_api_client_instance: MockAsyncClient,
) -> None:
"""get_session should keep the original ADK Event.id persisted in raw_event.

Regression test for the raw_event id being overwritten by the Vertex event
resource name, which made the same logical event report a different id
depending on whether it was observed via streaming or via a reload.
"""
mock_api_client_instance.session_dict['6'] = MOCK_SESSION_WITH_OVERRIDE_JSON
mock_api_client_instance.event_dict['6'] = (
copy.deepcopy(MOCK_EVENT_WITH_RAW_EVENT_ID_JSON),
None,
)
session_service = mock_vertex_ai_session_service()
session = await session_service.get_session(
app_name='123', user_id='user_with_override', session_id='6'
)
assert session is not None
assert len(session.events) == 1
assert (
session.events[0].id == 'c452feb0-b9ad-48b1-b863-c7dd2f085378'
), 'Event.id should come from raw_event, not the Vertex resource name.'


@pytest.mark.asyncio
@pytest.mark.usefixtures('mock_get_api_client')
async def test_get_session_with_many_events(mock_api_client_instance):
Expand Down
Loading