|
30 | 30 | from google.adk.a2a.converters.to_adk_event import convert_a2a_message_to_event |
31 | 31 | from google.adk.a2a.converters.to_adk_event import convert_a2a_status_update_to_event |
32 | 32 | from google.adk.a2a.converters.to_adk_event import convert_a2a_task_to_event |
| 33 | +from google.adk.a2a.converters.to_adk_event import MOCK_FUNCTION_CALL_FOR_REQUIRED_USER_INPUT |
33 | 34 | from google.adk.a2a.converters.utils import _get_adk_metadata_key |
34 | 35 | from google.adk.agents.invocation_context import InvocationContext |
35 | 36 | from google.genai import types as genai_types |
@@ -330,12 +331,95 @@ def test_convert_a2a_task_to_event_merges_status_and_artifact_actions(self): |
330 | 331 | assert event.actions.state_delta == {"saved_key": "saved-value"} |
331 | 332 | assert event.actions.transfer_to_agent == "agent-2" |
332 | 333 | assert event.content is not None |
333 | | - assert event.content.parts == [mock_genai_part] |
| 334 | + assert ( |
| 335 | + event.content.parts[0].function_call.name |
| 336 | + == MOCK_FUNCTION_CALL_FOR_REQUIRED_USER_INPUT |
| 337 | + ) |
| 338 | + assert ( |
| 339 | + event.content.parts[0].function_call.args["input_required"] |
| 340 | + == "need input" |
| 341 | + ) |
| 342 | + |
| 343 | + def test_convert_a2a_task_to_event_multiple_parts_replaces_last_text(self): |
| 344 | + """Test converting A2A task with multiple text parts, only replacing the last text.""" |
| 345 | + part1 = Mock(spec=A2APart) |
| 346 | + part1.root = Mock(spec=TextPart) |
| 347 | + part1.root.metadata = {} |
| 348 | + part2 = Mock(spec=A2APart) |
| 349 | + part2.root = Mock(spec=TextPart) |
| 350 | + part2.root.metadata = {} |
| 351 | + |
| 352 | + task = Task( |
| 353 | + id="task-1", |
| 354 | + context_id="context-1", |
| 355 | + kind="task", |
| 356 | + status=TaskStatus( |
| 357 | + state=TaskState.input_required, |
| 358 | + timestamp="now", |
| 359 | + message=Message( |
| 360 | + message_id="m1", |
| 361 | + role="agent", |
| 362 | + parts=[part1, part2], |
| 363 | + ), |
| 364 | + ), |
| 365 | + ) |
| 366 | + |
| 367 | + mock_genai_part_1 = genai_types.Part.from_text(text="Part 1") |
| 368 | + mock_genai_part_2 = genai_types.Part.from_text(text="Part 2") |
334 | 369 |
|
335 | | - def test_convert_a2a_task_to_event_none(self): |
336 | | - """Test convert_a2a_task_to_event with None.""" |
337 | | - with pytest.raises(ValueError, match="A2A task cannot be None"): |
338 | | - convert_a2a_task_to_event(None) |
| 370 | + part_converter_mock = Mock() |
| 371 | + part_converter_mock.side_effect = [[mock_genai_part_1], [mock_genai_part_2]] |
| 372 | + |
| 373 | + event = convert_a2a_task_to_event( |
| 374 | + task, |
| 375 | + author="test-author", |
| 376 | + invocation_context=self.mock_context, |
| 377 | + part_converter=part_converter_mock, |
| 378 | + ) |
| 379 | + |
| 380 | + assert event is not None |
| 381 | + assert event.content is not None |
| 382 | + assert len(event.content.parts) == 2 |
| 383 | + assert event.content.parts[0].text == "Part 1" |
| 384 | + assert ( |
| 385 | + event.content.parts[1].function_call.name |
| 386 | + == MOCK_FUNCTION_CALL_FOR_REQUIRED_USER_INPUT |
| 387 | + ) |
| 388 | + |
| 389 | + def test_convert_a2a_task_to_event_no_text_parts(self): |
| 390 | + """Test converting A2A task with no text parts should not inject function call.""" |
| 391 | + part1 = Mock(spec=A2APart) |
| 392 | + part1.root = Mock() # Not a TextPart |
| 393 | + part1.root.metadata = {} |
| 394 | + |
| 395 | + task = Task( |
| 396 | + id="task-1", |
| 397 | + context_id="context-1", |
| 398 | + kind="task", |
| 399 | + status=TaskStatus( |
| 400 | + state=TaskState.input_required, |
| 401 | + timestamp="now", |
| 402 | + message=Message( |
| 403 | + message_id="m1", |
| 404 | + role="agent", |
| 405 | + parts=[part1], |
| 406 | + ), |
| 407 | + ), |
| 408 | + ) |
| 409 | + mock_image_part = genai_types.Part( |
| 410 | + inline_data=genai_types.Blob(mime_type="image/jpeg", data=b"fake") |
| 411 | + ) |
| 412 | + |
| 413 | + event = convert_a2a_task_to_event( |
| 414 | + task, |
| 415 | + author="test-author", |
| 416 | + invocation_context=self.mock_context, |
| 417 | + part_converter=Mock(return_value=[mock_image_part]), |
| 418 | + ) |
| 419 | + |
| 420 | + assert event is not None |
| 421 | + assert event.content is not None |
| 422 | + assert event.content.parts == [mock_image_part] |
339 | 423 |
|
340 | 424 | def test_convert_a2a_status_update_to_event_success(self): |
341 | 425 | """Test successful conversion of A2A status update to Event.""" |
|
0 commit comments