|
24 | 24 | TaskStatus, |
25 | 25 | TaskStatusUpdateEvent, |
26 | 26 | TextPart, |
| 27 | + FilePart, |
| 28 | + DataPart, |
| 29 | + InvalidParamsError, |
27 | 30 | ) |
| 31 | +from a2a.utils.errors import ServerError |
28 | 32 |
|
29 | 33 |
|
30 | 34 | JSONRPC_URL = '/a2a/jsonrpc' |
@@ -67,6 +71,41 @@ async def execute( |
67 | 71 | task_id = context.task_id |
68 | 72 | context_id = context.context_id |
69 | 73 |
|
| 74 | + # Validate message parts |
| 75 | + if not user_message.parts: |
| 76 | + # Empty parts array is invalid |
| 77 | + raise ServerError( |
| 78 | + error=InvalidParamsError(message='Message must contain at least one part') |
| 79 | + ) |
| 80 | + |
| 81 | + for part in user_message.parts: |
| 82 | + # Unwrap RootModel if present to get the actual part |
| 83 | + actual_part = part |
| 84 | + if hasattr(part, 'root'): |
| 85 | + actual_part = part.root |
| 86 | + |
| 87 | + # Check if it's a known part type |
| 88 | + if not isinstance(actual_part, (TextPart, FilePart, DataPart)): |
| 89 | + # If we received something that isn't a known part, treating it as unsupported. |
| 90 | + # Enqueue a failed status event. |
| 91 | + await event_queue.enqueue_event(TaskStatusUpdateEvent( |
| 92 | + task_id=task_id, |
| 93 | + context_id=context_id, |
| 94 | + status=TaskStatus( |
| 95 | + state=TaskState.failed, |
| 96 | + message=Message( |
| 97 | + role='agent', |
| 98 | + message_id=str(uuid.uuid4()), |
| 99 | + parts=[TextPart(text='Unsupported message part type')], |
| 100 | + task_id=task_id, |
| 101 | + context_id=context_id, |
| 102 | + ), |
| 103 | + timestamp=datetime.now(timezone.utc).isoformat(), |
| 104 | + ), |
| 105 | + final=True, |
| 106 | + )) |
| 107 | + return |
| 108 | + |
70 | 109 | self.running_tasks.add(task_id) |
71 | 110 |
|
72 | 111 | logger.info( |
|
0 commit comments