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
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ public void getTask(org.a2aproject.sdk.grpc.GetTaskRequest request,
StreamObserver<org.a2aproject.sdk.grpc.Task> responseObserver) {
try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
TaskQueryParams params = FromProto.taskQueryParams(request);
Task task = getRequestHandler().onGetTask(params, context);
if (task != null) {
Expand All @@ -242,6 +244,8 @@ public void listTasks(org.a2aproject.sdk.grpc.ListTasksRequest request,
StreamObserver<org.a2aproject.sdk.grpc.ListTasksResponse> responseObserver) {
try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
org.a2aproject.sdk.spec.ListTasksParams params = FromProto.listTasksParams(request);
ListTasksResult result = getRequestHandler().onListTasks(params, context);
responseObserver.onNext(ToProto.listTasksResult(result));
Expand All @@ -260,6 +264,8 @@ public void cancelTask(org.a2aproject.sdk.grpc.CancelTaskRequest request,
StreamObserver<org.a2aproject.sdk.grpc.Task> responseObserver) {
try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
CancelTaskParams params = FromProto.cancelTaskParams(request);
Task task = getRequestHandler().onCancelTask(params, context);
if (task != null) {
Expand Down Expand Up @@ -287,6 +293,8 @@ public void createTaskPushNotificationConfig(org.a2aproject.sdk.grpc.TaskPushNot

try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
TaskPushNotificationConfig config = FromProto.createTaskPushNotificationConfig(request);
TaskPushNotificationConfig responseConfig = getRequestHandler().onCreateTaskPushNotificationConfig(config, context);
responseObserver.onNext(ToProto.taskPushNotificationConfig(responseConfig));
Expand All @@ -310,6 +318,8 @@ public void getTaskPushNotificationConfig(org.a2aproject.sdk.grpc.GetTaskPushNot

try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
GetTaskPushNotificationConfigParams params = FromProto.getTaskPushNotificationConfigParams(request);
TaskPushNotificationConfig config = getRequestHandler().onGetTaskPushNotificationConfig(params, context);
responseObserver.onNext(ToProto.taskPushNotificationConfig(config));
Expand All @@ -333,6 +343,8 @@ public void listTaskPushNotificationConfigs(org.a2aproject.sdk.grpc.ListTaskPush

try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
ListTaskPushNotificationConfigsParams params = FromProto.listTaskPushNotificationConfigsParams(request);
ListTaskPushNotificationConfigsResult result = getRequestHandler().onListTaskPushNotificationConfigs(params, context);
org.a2aproject.sdk.grpc.ListTaskPushNotificationConfigsResponse response = ToProto.listTaskPushNotificationConfigsResponse(result);
Expand Down Expand Up @@ -420,6 +432,8 @@ public void subscribeToTask(org.a2aproject.sdk.grpc.SubscribeToTaskRequest reque
try {
ServerCallContext context = createCallContext(responseObserver);
installForkedContextWrapper(context);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
TaskIdParams params = FromProto.taskIdParams(request);
Flow.Publisher<StreamingEventKind> publisher = getRequestHandler().onSubscribeToTask(params, context);
convertToStreamResponse(publisher, responseObserver, context);
Expand Down Expand Up @@ -568,6 +582,9 @@ public void getExtendedAgentCard(org.a2aproject.sdk.grpc.GetExtendedAgentCardReq
handleError(responseObserver, new UnsupportedOperationError());
return;
}
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
AgentCard extendedAgentCard = getExtendedAgentCard();
if (extendedAgentCard != null) {
responseObserver.onNext(ToProto.agentCard(extendedAgentCard));
Expand All @@ -591,6 +608,8 @@ public void deleteTaskPushNotificationConfig(org.a2aproject.sdk.grpc.DeleteTaskP

try {
ServerCallContext context = createCallContext(responseObserver);
A2AVersionValidator.validateProtocolVersion(getAgentCardInternal(), context);
A2AExtensions.validateRequiredExtensions(getAgentCardInternal(), context);
DeleteTaskPushNotificationConfigParams params = FromProto.deleteTaskPushNotificationConfigParams(request);
getRequestHandler().onDeleteTaskPushNotificationConfig(params, context);
// void response
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,52 @@ public <V> ServerCallContext create(StreamObserver<V> streamObserver) {
assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
}

@Test
public void testVersionNotSupportedErrorOnGetTask() throws Exception {
// Regression test for BUG-33: getTask previously skipped A2A protocol version
// and extension validation, unlike sendMessage/sendStreamingMessage.
AgentCard agentCard = AgentCard.builder()
.name("test-card")
.description("Test card with version 1.0")
.supportedInterfaces(Collections.singletonList(new AgentInterface("GRPC", "http://localhost:9999")))
.version("1.0.0")
.capabilities(AgentCapabilities.builder()
.streaming(true)
.pushNotifications(false)
.build())
.defaultInputModes(List.of("text"))
.defaultOutputModes(List.of("text"))
.skills(List.of())
.build();

// Create handler that provides incompatible version 2.0 in the context
GrpcHandler handler = new TestGrpcHandler(agentCard, requestHandler, internalExecutor) {
@Override
protected CallContextFactory getCallContextFactory() {
return new CallContextFactory() {
@Override
public <V> ServerCallContext create(StreamObserver<V> streamObserver) {
return new ServerCallContext(
UnauthenticatedUser.INSTANCE,
Map.of("grpc_response_observer", streamObserver),
new HashSet<>(),
"2.0" // Incompatible version
);
}
};
}
};

GetTaskRequest request = GetTaskRequest.newBuilder()
.setId(AbstractA2ARequestHandlerTest.MINIMAL_TASK.id())
.build();
StreamRecorder<Task> streamRecorder = StreamRecorder.create();
handler.getTask(request, streamRecorder);
streamRecorder.awaitCompletion(5, TimeUnit.SECONDS);

assertGrpcError(streamRecorder, Status.Code.UNIMPLEMENTED);
}

@Test
public void testCompatibleVersionSuccess() throws Exception {
// Create AgentCard with protocol version 1.0
Expand Down
Loading