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
106 changes: 67 additions & 39 deletions src/google/adk/a2a/converters/part_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,30 @@ def convert_a2a_part_to_genai_part(
) -> Optional[genai_types.Part]:
"""Convert an A2A Part to a Google GenAI Part."""
part = a2a_part.root

thought = None
if part.metadata:
thought = part.metadata.get(_get_adk_metadata_key('thought'))

if isinstance(part, a2a_types.TextPart):
return genai_types.Part(text=part.text)
return genai_types.Part(text=part.text, thought=thought)

if isinstance(part, a2a_types.FilePart):
if isinstance(part.file, a2a_types.FileWithUri):
return genai_types.Part(
file_data=genai_types.FileData(
file_uri=part.file.uri, mime_type=part.file.mime_type
)
),
thought=thought,
)

elif isinstance(part.file, a2a_types.FileWithBytes):
return genai_types.Part(
inline_data=genai_types.Blob(
data=base64.b64decode(part.file.bytes),
mime_type=part.file.mime_type,
)
),
thought=thought,
)
else:
logger.warning(
Expand Down Expand Up @@ -104,7 +111,8 @@ def convert_a2a_part_to_genai_part(
return genai_types.Part(
function_call=genai_types.FunctionCall.model_validate(
part.data, by_alias=True
)
),
thought=thought,
)
if (
part.metadata[_get_adk_metadata_key(A2A_DATA_PART_METADATA_TYPE_KEY)]
Expand All @@ -113,7 +121,8 @@ def convert_a2a_part_to_genai_part(
return genai_types.Part(
function_response=genai_types.FunctionResponse.model_validate(
part.data, by_alias=True
)
),
thought=thought,
)
if (
part.metadata[_get_adk_metadata_key(A2A_DATA_PART_METADATA_TYPE_KEY)]
Expand All @@ -122,7 +131,8 @@ def convert_a2a_part_to_genai_part(
return genai_types.Part(
code_execution_result=genai_types.CodeExecutionResult.model_validate(
part.data, by_alias=True
)
),
thought=thought,
)
if (
part.metadata[_get_adk_metadata_key(A2A_DATA_PART_METADATA_TYPE_KEY)]
Expand All @@ -131,7 +141,8 @@ def convert_a2a_part_to_genai_part(
return genai_types.Part(
executable_code=genai_types.ExecutableCode.model_validate(
part.data, by_alias=True
)
),
thought=thought,
)
return genai_types.Part(
inline_data=genai_types.Blob(
Expand All @@ -141,7 +152,8 @@ def convert_a2a_part_to_genai_part(
)
+ A2A_DATA_PART_END_TAG,
mime_type=A2A_DATA_PART_TEXT_MIME_TYPE,
)
),
thought=thought,
)

logger.warning(
Expand All @@ -165,14 +177,15 @@ def convert_genai_part_to_a2a_part(
return a2a_types.Part(root=a2a_part)

if part.file_data:
return a2a_types.Part(
root=a2a_types.FilePart(
file=a2a_types.FileWithUri(
uri=part.file_data.file_uri,
mime_type=part.file_data.mime_type,
)
a2a_part = a2a_types.FilePart(
file=a2a_types.FileWithUri(
uri=part.file_data.file_uri,
mime_type=part.file_data.mime_type,
)
)
if part.thought is not None:
a2a_part.metadata = {_get_adk_metadata_key('thought'): part.thought}
return a2a_types.Part(root=a2a_part)

if part.inline_data:
if (
Expand All @@ -196,12 +209,15 @@ def convert_genai_part_to_a2a_part(
)
)

metadata = {}
if part.video_metadata:
a2a_part.metadata = {
_get_adk_metadata_key(
'video_metadata'
): part.video_metadata.model_dump(by_alias=True, exclude_none=True)
}
metadata[_get_adk_metadata_key('video_metadata')] = (
part.video_metadata.model_dump(by_alias=True, exclude_none=True)
)
if part.thought is not None:
metadata[_get_adk_metadata_key('thought')] = part.thought
if metadata:
a2a_part.metadata = metadata

return a2a_types.Part(root=a2a_part)

Expand All @@ -211,58 +227,70 @@ def convert_genai_part_to_a2a_part(
# TODO once A2A defined how to service such information, migrate below
# logic accordingly
if part.function_call:
metadata = {
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_FUNCTION_CALL
}
if part.thought is not None:
metadata[_get_adk_metadata_key('thought')] = part.thought
return a2a_types.Part(
root=a2a_types.DataPart(
data=part.function_call.model_dump(
by_alias=True, exclude_none=True
),
metadata={
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_FUNCTION_CALL
},
metadata=metadata,
)
)

if part.function_response:
metadata = {
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_FUNCTION_RESPONSE
}
if part.thought is not None:
metadata[_get_adk_metadata_key('thought')] = part.thought
return a2a_types.Part(
root=a2a_types.DataPart(
data=part.function_response.model_dump(
by_alias=True, exclude_none=True
),
metadata={
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_FUNCTION_RESPONSE
},
metadata=metadata,
)
)

if part.code_execution_result:
metadata = {
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_CODE_EXECUTION_RESULT
}
if part.thought is not None:
metadata[_get_adk_metadata_key('thought')] = part.thought
return a2a_types.Part(
root=a2a_types.DataPart(
data=part.code_execution_result.model_dump(
by_alias=True, exclude_none=True
),
metadata={
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_CODE_EXECUTION_RESULT
},
metadata=metadata,
)
)

if part.executable_code:
metadata = {
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_EXECUTABLE_CODE
}
if part.thought is not None:
metadata[_get_adk_metadata_key('thought')] = part.thought
return a2a_types.Part(
root=a2a_types.DataPart(
data=part.executable_code.model_dump(
by_alias=True, exclude_none=True
),
metadata={
_get_adk_metadata_key(
A2A_DATA_PART_METADATA_TYPE_KEY
): A2A_DATA_PART_METADATA_TYPE_EXECUTABLE_CODE
},
metadata=metadata,
)
)

Expand Down
Loading