diff --git a/boms/sdk/pom.xml b/boms/sdk/pom.xml index c0b51b73a..c9354f558 100644 --- a/boms/sdk/pom.xml +++ b/boms/sdk/pom.xml @@ -39,6 +39,11 @@ a2a-java-sdk-common ${project.version} + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-http-client diff --git a/client/base/src/main/java/io/a2a/client/AbstractClient.java b/client/base/src/main/java/io/a2a/client/AbstractClient.java index 414c25f73..b61623668 100644 --- a/client/base/src/main/java/io/a2a/client/AbstractClient.java +++ b/client/base/src/main/java/io/a2a/client/AbstractClient.java @@ -8,6 +8,7 @@ import java.util.function.Consumer; import io.a2a.client.transport.spi.interceptors.ClientCallContext; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; @@ -15,7 +16,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; diff --git a/client/base/src/main/java/io/a2a/client/Client.java b/client/base/src/main/java/io/a2a/client/Client.java index cb8ef954b..2a82b872e 100644 --- a/client/base/src/main/java/io/a2a/client/Client.java +++ b/client/base/src/main/java/io/a2a/client/Client.java @@ -1,13 +1,16 @@ package io.a2a.client; +import static io.a2a.util.Assert.checkNotNullParam; + import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; import io.a2a.client.config.ClientConfig; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; import io.a2a.client.transport.spi.ClientTransport; +import io.a2a.client.transport.spi.interceptors.ClientCallContext; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientError; import io.a2a.spec.A2AClientException; import io.a2a.spec.A2AClientInvalidStateError; @@ -18,7 +21,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; @@ -30,9 +32,6 @@ import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskStatusUpdateEvent; - -import static io.a2a.util.Assert.checkNotNullParam; - import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; diff --git a/client/base/src/main/java/io/a2a/client/ClientBuilder.java b/client/base/src/main/java/io/a2a/client/ClientBuilder.java index 164d83aeb..b05b44ca1 100644 --- a/client/base/src/main/java/io/a2a/client/ClientBuilder.java +++ b/client/base/src/main/java/io/a2a/client/ClientBuilder.java @@ -1,5 +1,14 @@ package io.a2a.client; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + import io.a2a.client.config.ClientConfig; import io.a2a.client.transport.spi.ClientTransport; import io.a2a.client.transport.spi.ClientTransportConfig; @@ -9,15 +18,6 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.TransportProtocol; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.ServiceLoader; -import java.util.function.BiConsumer; -import java.util.function.Consumer; import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; diff --git a/client/base/src/main/java/io/a2a/client/config/ClientConfig.java b/client/base/src/main/java/io/a2a/client/config/ClientConfig.java index 0f4672aa9..823548c23 100644 --- a/client/base/src/main/java/io/a2a/client/config/ClientConfig.java +++ b/client/base/src/main/java/io/a2a/client/config/ClientConfig.java @@ -1,11 +1,11 @@ package io.a2a.client.config; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import io.a2a.spec.PushNotificationConfig; -import java.util.ArrayList; -import java.util.HashMap; import org.jspecify.annotations.Nullable; /** diff --git a/client/base/src/test/java/io/a2a/A2ATest.java b/client/base/src/test/java/io/a2a/A2ATest.java index 217bb18c9..0f4d3eaa5 100644 --- a/client/base/src/test/java/io/a2a/A2ATest.java +++ b/client/base/src/test/java/io/a2a/A2ATest.java @@ -1,17 +1,17 @@ package io.a2a; -import io.a2a.spec.Message; -import io.a2a.spec.Part; -import io.a2a.spec.TextPart; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import java.util.Arrays; import java.util.Collections; import java.util.List; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import io.a2a.spec.Message; +import io.a2a.spec.Part; +import io.a2a.spec.TextPart; +import org.junit.jupiter.api.Test; public class A2ATest { diff --git a/client/transport/grpc/pom.xml b/client/transport/grpc/pom.xml index 7965dcaa2..65c0b8514 100644 --- a/client/transport/grpc/pom.xml +++ b/client/transport/grpc/pom.xml @@ -25,6 +25,11 @@ ${project.groupId} a2a-java-sdk-spec + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-spec-grpc diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java index 627286607..d77b81824 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java +++ b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/EventStreamObserver.java @@ -1,14 +1,14 @@ package io.a2a.client.transport.grpc; -import io.a2a.grpc.StreamResponse; -import io.a2a.spec.StreamingEventKind; -import io.grpc.stub.StreamObserver; +import static io.a2a.grpc.utils.ProtoUtils.FromProto; import java.util.function.Consumer; import java.util.logging.Logger; -import static io.a2a.grpc.utils.ProtoUtils.FromProto; +import io.a2a.grpc.StreamResponse; +import io.a2a.spec.StreamingEventKind; +import io.grpc.stub.StreamObserver; public class EventStreamObserver implements StreamObserver { diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java index a846210d9..207ccc45b 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java +++ b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransport.java @@ -1,5 +1,15 @@ package io.a2a.client.transport.grpc; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; import static io.a2a.util.Assert.checkNotNullParam; import java.util.List; @@ -7,8 +17,8 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import io.a2a.client.transport.spi.interceptors.ClientCallContext; import io.a2a.client.transport.spi.ClientTransport; +import io.a2a.client.transport.spi.interceptors.ClientCallContext; import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; import io.a2a.client.transport.spi.interceptors.auth.AuthInterceptor; @@ -18,27 +28,17 @@ import io.a2a.grpc.A2AServiceGrpc.A2AServiceStub; import io.a2a.grpc.utils.ProtoUtils.FromProto; import io.a2a.grpc.utils.ProtoUtils.ToProto; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskRequest; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; import io.a2a.spec.EventKind; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskRequest; import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; import io.a2a.spec.TaskPushNotificationConfig; @@ -95,7 +95,7 @@ public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallCont MessageSendParams tenantRequest = createRequestWithTenant(request); io.a2a.grpc.SendMessageRequest sendMessageRequest = createGrpcSendMessageRequest(tenantRequest, context); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SendMessageRequest.METHOD, sendMessageRequest, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, sendMessageRequest, agentCard, context); try { @@ -121,7 +121,7 @@ public void sendMessageStreaming(MessageSendParams request, Consumer streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); @@ -143,7 +143,7 @@ public Task getTask(TaskQueryParams request, @Nullable ClientCallContext context } requestBuilder.setTenant(resolveTenant(request.tenant())); io.a2a.grpc.GetTaskRequest getTaskRequest = requestBuilder.build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskRequest.METHOD, getTaskRequest, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_METHOD, getTaskRequest, agentCard, context); try { @@ -162,8 +162,7 @@ public Task cancelTask(TaskIdParams request, @Nullable ClientCallContext context .setName("tasks/" + request.id()) .setTenant(resolveTenant(request.tenant())) .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(CancelTaskRequest.METHOD, cancelTaskRequest, - agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(CANCEL_TASK_METHOD, cancelTaskRequest, agentCard, context); try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); @@ -201,8 +200,7 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo } requestBuilder.setTenant(resolveTenant(request.tenant())); io.a2a.grpc.ListTasksRequest listTasksRequest = requestBuilder.build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(ListTasksRequest.METHOD, listTasksRequest, - agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_METHOD, listTasksRequest, agentCard, context); try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); @@ -233,8 +231,7 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN .setConfigId(configId != null ? configId : request.taskId()) .setTenant(resolveTenant(request.tenant())) .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SetTaskPushNotificationConfigRequest.METHOD, - grpcRequest, agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); @@ -254,8 +251,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration( .setName(getTaskPushNotificationConfigName(request)) .setTenant(resolveTenant(request.tenant())) .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskPushNotificationConfigRequest.METHOD, - grpcRequest, agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); @@ -277,7 +273,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio .setPageSize(request.pageSize()) .setPageToken(request.pageToken()) .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest.METHOD, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); try { @@ -298,8 +294,7 @@ public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationC .setName(getTaskPushNotificationConfigName(request.id(), request.pushNotificationConfigId())) .setTenant(resolveTenant(request.tenant())) .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(DeleteTaskPushNotificationConfigRequest.METHOD, - grpcRequest, agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, grpcRequest, agentCard, context); try { A2AServiceBlockingV2Stub stubWithMetadata = createBlockingStubWithMetadata(context, payloadAndHeaders); @@ -319,8 +314,7 @@ public void resubscribe(TaskIdParams request, Consumer event .setTenant(resolveTenant(request.tenant())) .setName("tasks/" + request.id()) .build(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SubscribeToTaskRequest.METHOD, - grpcRequest, agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, grpcRequest, agentCard, context); StreamObserver streamObserver = new EventStreamObserver(eventConsumer, errorConsumer); diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java index c6fe443d2..a1bc3373c 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java +++ b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfig.java @@ -1,11 +1,11 @@ package io.a2a.client.transport.grpc; +import java.util.function.Function; + import io.a2a.client.transport.spi.ClientTransportConfig; import io.a2a.util.Assert; import io.grpc.Channel; -import java.util.function.Function; - public class GrpcTransportConfig extends ClientTransportConfig { private final Function channelFactory; diff --git a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java index 6878ce7d4..138fadb1f 100644 --- a/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java +++ b/client/transport/grpc/src/main/java/io/a2a/client/transport/grpc/GrpcTransportConfigBuilder.java @@ -1,11 +1,10 @@ package io.a2a.client.transport.grpc; +import java.util.function.Function; + import io.a2a.client.transport.spi.ClientTransportConfigBuilder; import io.a2a.util.Assert; import io.grpc.Channel; - -import java.util.function.Function; - import org.jspecify.annotations.Nullable; public class GrpcTransportConfigBuilder extends ClientTransportConfigBuilder { diff --git a/client/transport/jsonrpc/pom.xml b/client/transport/jsonrpc/pom.xml index 3961bdaf2..19084ad9d 100644 --- a/client/transport/jsonrpc/pom.xml +++ b/client/transport/jsonrpc/pom.xml @@ -33,6 +33,11 @@ ${project.groupId} a2a-java-sdk-spec + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-spec-grpc diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java index 250503f96..69e291988 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java +++ b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransport.java @@ -1,5 +1,16 @@ package io.a2a.client.transport.jsonrpc; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; import static io.a2a.util.Assert.checkNotNullParam; import java.io.IOException; @@ -9,7 +20,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; -import io.a2a.json.JsonProcessingException; import com.google.protobuf.MessageOrBuilder; import io.a2a.client.http.A2ACardResolver; import io.a2a.client.http.A2AHttpClient; @@ -22,42 +32,33 @@ import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; import io.a2a.grpc.utils.JSONRPCUtils; import io.a2a.grpc.utils.ProtoUtils; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.wrappers.A2AMessage; +import io.a2a.jsonrpc.common.wrappers.A2AResponse; +import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; import io.a2a.spec.A2AClientError; import io.a2a.spec.A2AClientException; +import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.CancelTaskResponse; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigResponse; import io.a2a.spec.EventKind; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; -import io.a2a.spec.GetAuthenticatedExtendedCardResponse; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.GetTaskResponse; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.JSONRPCMessage; -import io.a2a.spec.JSONRPCResponse; import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTaskPushNotificationConfigResponse; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.ListTasksResponse; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendMessageResponse; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; import io.a2a.spec.TaskPushNotificationConfig; @@ -93,12 +94,12 @@ public JSONRPCTransport(@Nullable A2AHttpClient httpClient, @Nullable AgentCard @Override public EventKind sendMessage(MessageSendParams request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SendMessageRequest.METHOD, ProtoUtils.ToProto.sendMessageRequest(request), + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, ProtoUtils.ToProto.sendMessageRequest(request), agentCard, context); try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SendMessageRequest.METHOD); - SendMessageResponse response = unmarshalResponse(httpResponseBody, SendMessageRequest.METHOD); + String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SEND_MESSAGE_METHOD); + SendMessageResponse response = unmarshalResponse(httpResponseBody, SEND_MESSAGE_METHOD); return response.getResult(); } catch (A2AClientException e) { throw e; @@ -112,14 +113,14 @@ public void sendMessageStreaming(MessageSendParams request, Consumer errorConsumer, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); checkNotNullParam("eventConsumer", eventConsumer); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SendStreamingMessageRequest.METHOD, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_STREAMING_MESSAGE_METHOD, ProtoUtils.ToProto.sendMessageRequest(request), agentCard, context); final AtomicReference> ref = new AtomicReference<>(); SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); try { - A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SendStreamingMessageRequest.METHOD); + A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SEND_STREAMING_MESSAGE_METHOD); ref.set(builder.postAsyncSSE( msg -> sseEventListener.onMessage(msg, ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), @@ -139,12 +140,12 @@ public void sendMessageStreaming(MessageSendParams request, Consumer event checkNotNullParam("request", request); checkNotNullParam("eventConsumer", eventConsumer); checkNotNullParam("errorConsumer", errorConsumer); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SubscribeToTaskRequest.METHOD, - ProtoUtils.ToProto.subscribeToTaskRequest(request), agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, ProtoUtils.ToProto.subscribeToTaskRequest(request), agentCard, context); AtomicReference> ref = new AtomicReference<>(); SSEEventListener sseEventListener = new SSEEventListener(eventConsumer, errorConsumer); try { - A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders,SubscribeToTaskRequest.METHOD); + A2AHttpClient.PostBuilder builder = createPostBuilder(Utils.buildBaseUrl(agentInterface, request.tenant()), payloadAndHeaders, SUBSCRIBE_TO_TASK_METHOD); ref.set(builder.postAsyncSSE( msg -> sseEventListener.onMessage(msg, ref.get()), throwable -> sseEventListener.onError(throwable, ref.get()), @@ -304,16 +301,15 @@ public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2ACli } GetAuthenticatedExtendedCardRequest getExtendedAgentCardRequest = GetAuthenticatedExtendedCardRequest.builder() - .jsonrpc(JSONRPCMessage.JSONRPC_VERSION) + .jsonrpc(A2AMessage.JSONRPC_VERSION) .build(); // id will be randomly generated - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetAuthenticatedExtendedCardRequest.METHOD, - ProtoUtils.ToProto.extendedAgentCard(getExtendedAgentCardRequest), agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, + ProtoUtils.ToProto.extendedAgentCard(), agentCard, context); try { - String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, ""), payloadAndHeaders,GetAuthenticatedExtendedCardRequest.METHOD); - GetAuthenticatedExtendedCardResponse response = unmarshalResponse(httpResponseBody, - GetAuthenticatedExtendedCardRequest.METHOD); + String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, ""), payloadAndHeaders, GET_EXTENDED_AGENT_CARD_METHOD); + GetAuthenticatedExtendedCardResponse response = unmarshalResponse(httpResponseBody, GET_EXTENDED_AGENT_CARD_METHOD); agentCard = response.getResult(); needsExtendedCard = false; return agentCard; @@ -381,10 +377,10 @@ private A2AHttpClient.PostBuilder createPostBuilder(String url, PayloadAndHeader * @throws JsonProcessingException if the JSON cannot be processed */ @SuppressWarnings("unchecked") - private > T unmarshalResponse(String response, String method) + private > T unmarshalResponse(String response, String method) throws A2AClientException, JsonProcessingException { - JSONRPCResponse value = JSONRPCUtils.parseResponseBody(response, method); - JSONRPCError error = value.getError(); + A2AResponse value = JSONRPCUtils.parseResponseBody(response, method); + A2AError error = value.getError(); if (error != null) { throw new A2AClientException(error.getMessage() + (error.getData() != null ? ": " + error.getData() : ""), error); } diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java index 364cc4715..0705faf20 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java +++ b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportConfig.java @@ -1,7 +1,7 @@ package io.a2a.client.transport.jsonrpc; -import io.a2a.client.transport.spi.ClientTransportConfig; import io.a2a.client.http.A2AHttpClient; +import io.a2a.client.transport.spi.ClientTransportConfig; import org.jspecify.annotations.Nullable; public class JSONRPCTransportConfig extends ClientTransportConfig { diff --git a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java index f940f09d7..33025ed5e 100644 --- a/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java +++ b/client/transport/jsonrpc/src/main/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListener.java @@ -1,10 +1,5 @@ package io.a2a.client.transport.jsonrpc.sse; -import io.a2a.json.JsonProcessingException; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskStatusUpdateEvent; - import java.util.concurrent.Future; import java.util.function.Consumer; import java.util.logging.Logger; @@ -12,6 +7,10 @@ import io.a2a.grpc.StreamResponse; import io.a2a.grpc.utils.JSONRPCUtils; import io.a2a.grpc.utils.ProtoUtils; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.spec.A2AError; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.TaskStatusUpdateEvent; import org.jspecify.annotations.Nullable; public class SSEEventListener { @@ -70,7 +69,7 @@ private void handleMessage(String message, @Nullable Future future) { future.cancel(true); // close SSE channel } } - } catch (JSONRPCError error) { + } catch (A2AError error) { if (errorHandler != null) { errorHandler.accept(error); } diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java index 92541eb20..c994ff89d 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JSONRPCTransportStreamingTest.java @@ -28,7 +28,6 @@ import io.a2a.spec.TaskIdParams; import io.a2a.spec.TaskState; import io.a2a.spec.TextPart; - import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java index 3ad728e2d..27c27a7ab 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/JsonMessages.java @@ -2,8 +2,6 @@ import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; -import io.a2a.spec.AgentCard; - /** * Request and response messages used by the tests. These have been created following examples from * the A2A sample messages. diff --git a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java index 6855e1dcc..17f805312 100644 --- a/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java +++ b/client/transport/jsonrpc/src/test/java/io/a2a/client/transport/jsonrpc/sse/SSEEventListenerTest.java @@ -14,10 +14,9 @@ import java.util.concurrent.atomic.AtomicReference; import io.a2a.client.transport.jsonrpc.JsonStreamingMessages; +import io.a2a.spec.A2AError; import io.a2a.spec.Artifact; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; -import io.a2a.spec.Part; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -158,8 +157,8 @@ public void testOnEventWithError() throws Exception { // Verify the error was processed correctly assertNotNull(receivedError.get()); - assertInstanceOf(JSONRPCError.class, receivedError.get()); - JSONRPCError jsonrpcError = (JSONRPCError) receivedError.get(); + assertInstanceOf(A2AError.class, receivedError.get()); + A2AError jsonrpcError = (A2AError) receivedError.get(); assertEquals(-32602, jsonrpcError.getCode()); assertEquals("Invalid parameters", jsonrpcError.getMessage()); assertEquals("\"Missing required field\"", jsonrpcError.getData()); diff --git a/client/transport/rest/pom.xml b/client/transport/rest/pom.xml index 4353383c0..3ded0dee9 100644 --- a/client/transport/rest/pom.xml +++ b/client/transport/rest/pom.xml @@ -25,6 +25,11 @@ ${project.groupId} a2a-java-sdk-spec + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-spec-grpc diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java index c23eab4a0..c6cb181b4 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java +++ b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestErrorMapper.java @@ -1,9 +1,12 @@ package io.a2a.client.transport.rest; +import java.util.logging.Level; +import java.util.logging.Logger; + import com.google.gson.JsonObject; import io.a2a.client.http.A2AHttpResponse; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.A2AClientException; import io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError; import io.a2a.spec.ContentTypeNotSupportedError; @@ -17,8 +20,6 @@ import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.UnsupportedOperationError; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Utility class to A2AHttpResponse to appropriate A2A error types diff --git a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java index 500daf6f8..0f9fcd5b9 100644 --- a/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java +++ b/client/transport/rest/src/main/java/io/a2a/client/transport/rest/RestTransport.java @@ -1,5 +1,16 @@ package io.a2a.client.transport.rest; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; import static io.a2a.util.Assert.checkNotNullParam; import java.io.IOException; @@ -13,7 +24,6 @@ import java.util.function.Consumer; import java.util.logging.Logger; -import io.a2a.json.JsonProcessingException; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.MessageOrBuilder; import com.google.protobuf.util.JsonFormat; @@ -27,30 +37,21 @@ import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; import io.a2a.client.transport.spi.interceptors.PayloadAndHeaders; import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientError; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; -import io.a2a.spec.CancelTaskRequest; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; import io.a2a.spec.EventKind; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskRequest; import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.MessageSendParams; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.Task; import io.a2a.spec.TaskIdParams; import io.a2a.spec.TaskPushNotificationConfig; @@ -83,7 +84,7 @@ public RestTransport(@Nullable A2AHttpClient httpClient, AgentCard agentCard, public EventKind sendMessage(MessageSendParams messageSendParams, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("messageSendParams", messageSendParams); io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(ProtoUtils.ToProto.sendMessageRequest(messageSendParams)); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SendMessageRequest.METHOD, builder, agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SEND_MESSAGE_METHOD, builder, agentCard, context); try { String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, messageSendParams.tenant()) + "/message:send", payloadAndHeaders); io.a2a.grpc.SendMessageResponse.Builder responseBuilder = io.a2a.grpc.SendMessageResponse.newBuilder(); @@ -108,8 +109,7 @@ public void sendMessageStreaming(MessageSendParams messageSendParams, Consumer> ref = new AtomicReference<>(); RestSSEEventListener sseEventListener = new RestSSEEventListener(eventConsumer, errorConsumer); try { @@ -134,8 +134,7 @@ public Task getTask(TaskQueryParams taskQueryParams, @Nullable ClientCallContext checkNotNullParam("taskQueryParams", taskQueryParams); io.a2a.grpc.GetTaskRequest.Builder builder = io.a2a.grpc.GetTaskRequest.newBuilder(); builder.setName("tasks/" + taskQueryParams.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskRequest.METHOD, builder, - agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_METHOD, builder, agentCard, context); try { StringBuilder url = new StringBuilder(Utils.buildBaseUrl(agentInterface, taskQueryParams.tenant())); if (taskQueryParams.historyLength() != null && taskQueryParams.historyLength() > 0) { @@ -169,8 +168,7 @@ public Task cancelTask(TaskIdParams taskIdParams, @Nullable ClientCallContext co checkNotNullParam("taskIdParams", taskIdParams); io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); builder.setName("tasks/" + taskIdParams.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(CancelTaskRequest.METHOD, builder, - agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(CANCEL_TASK_METHOD, builder, agentCard, context); try { String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, taskIdParams.tenant()) + String.format("/tasks/%1s:cancel", taskIdParams.id()), payloadAndHeaders); io.a2a.grpc.Task.Builder responseBuilder = io.a2a.grpc.Task.newBuilder(); @@ -209,8 +207,7 @@ public ListTasksResult listTasks(ListTasksParams request, @Nullable ClientCallCo builder.setIncludeArtifacts(true); } - PayloadAndHeaders payloadAndHeaders = applyInterceptors(ListTasksRequest.METHOD, builder, - agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_METHOD, builder, agentCard, context); try { // Build query string @@ -282,7 +279,7 @@ public TaskPushNotificationConfig setTaskPushNotificationConfiguration(TaskPushN if (request.pushNotificationConfig().id() != null) { builder.setConfigId(request.pushNotificationConfig().id()); } - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SetTaskPushNotificationConfigRequest.METHOD, builder, agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); try { String httpResponseBody = sendPostRequest(Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs", request.taskId()), payloadAndHeaders); io.a2a.grpc.TaskPushNotificationConfig.Builder responseBuilder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); @@ -310,7 +307,7 @@ public TaskPushNotificationConfig getTaskPushNotificationConfiguration(GetTaskPu builder.setName(String.format("/tasks/%1s/pushNotificationConfigs/", request.id())); url.append(builder.getName()); } - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskPushNotificationConfigRequest.METHOD, builder, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); try { A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url.toString()); @@ -340,7 +337,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); builder.setParent(String.format("/tasks/%1s/pushNotificationConfigs", request.id())); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(ListTaskPushNotificationConfigRequest.METHOD, builder, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); try { String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs", request.id()); @@ -369,7 +366,7 @@ public ListTaskPushNotificationConfigResult listTaskPushNotificationConfiguratio public void deleteTaskPushNotificationConfigurations(DeleteTaskPushNotificationConfigParams request, @Nullable ClientCallContext context) throws A2AClientException { checkNotNullParam("request", request); io.a2a.grpc.DeleteTaskPushNotificationConfigRequestOrBuilder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(DeleteTaskPushNotificationConfigRequest.METHOD, builder, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, builder, agentCard, context); try { String url = Utils.buildBaseUrl(agentInterface, request.tenant()) + String.format("/tasks/%1s/pushNotificationConfigs/%2s", request.id(), request.pushNotificationConfigId()); @@ -396,7 +393,7 @@ public void resubscribe(TaskIdParams request, Consumer event checkNotNullParam("request", request); io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); builder.setName("tasks/" + request.id()); - PayloadAndHeaders payloadAndHeaders = applyInterceptors(SubscribeToTaskRequest.METHOD, builder, + PayloadAndHeaders payloadAndHeaders = applyInterceptors(SUBSCRIBE_TO_TASK_METHOD, builder, agentCard, context); AtomicReference> ref = new AtomicReference<>(); RestSSEEventListener sseEventListener = new RestSSEEventListener(eventConsumer, errorConsumer); @@ -430,8 +427,7 @@ public AgentCard getAgentCard(@Nullable ClientCallContext context) throws A2ACli if (!needsExtendedCard) { return agentCard; } - PayloadAndHeaders payloadAndHeaders = applyInterceptors(GetTaskRequest.METHOD, null, - agentCard, context); + PayloadAndHeaders payloadAndHeaders = applyInterceptors(GET_EXTENDED_AGENT_CARD_METHOD, null, agentCard, context); String url = Utils.buildBaseUrl(agentInterface, "") + "/extendedAgentCard"; A2AHttpClient.GetBuilder getBuilder = httpClient.createGet().url(url); if (payloadAndHeaders.getHeaders() != null) { diff --git a/client/transport/spi/pom.xml b/client/transport/spi/pom.xml index bb806abb8..3230d21fe 100644 --- a/client/transport/spi/pom.xml +++ b/client/transport/spi/pom.xml @@ -21,6 +21,11 @@ io.github.a2asdk a2a-java-sdk-spec + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + org.junit.jupiter junit-jupiter-api diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java index 4b978c717..e0f4b3a0c 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransport.java @@ -1,9 +1,9 @@ package io.a2a.client.transport.spi; -import java.util.List; import java.util.function.Consumer; import io.a2a.client.transport.spi.interceptors.ClientCallContext; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; @@ -12,7 +12,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.MessageSendParams; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java index 8efdb779b..c04b52882 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfig.java @@ -1,10 +1,10 @@ package io.a2a.client.transport.spi; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; import java.util.ArrayList; - import java.util.List; +import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; + /** * Configuration for an A2A client transport. */ diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java index 0858f910b..6dbd9ea60 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/ClientTransportConfigBuilder.java @@ -1,10 +1,10 @@ package io.a2a.client.transport.spi; -import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; - import java.util.ArrayList; import java.util.List; +import io.a2a.client.transport.spi.interceptors.ClientCallInterceptor; + public abstract class ClientTransportConfigBuilder, B extends ClientTransportConfigBuilder> { diff --git a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java index 816ad3e5f..7f8075312 100644 --- a/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java +++ b/client/transport/spi/src/main/java/io/a2a/client/transport/spi/interceptors/PayloadAndHeaders.java @@ -3,6 +3,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; + import org.jspecify.annotations.Nullable; public class PayloadAndHeaders { diff --git a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java index 642c1e0ee..0aeacff66 100644 --- a/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java +++ b/client/transport/spi/src/test/java/io/a2a/client/transport/spi/interceptors/auth/AuthInterceptorTest.java @@ -19,7 +19,6 @@ import io.a2a.spec.OAuthFlows; import io.a2a.spec.OpenIdConnectSecurityScheme; import io.a2a.spec.SecurityScheme; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java index 7ba9f1d76..d3d36044d 100644 --- a/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java +++ b/examples/cloud-deployment/server/src/main/java/io/a2a/examples/cloud/CloudAgentExecutorProducer.java @@ -1,21 +1,22 @@ package io.a2a.examples.cloud; +import java.util.List; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; +import io.a2a.spec.A2AError; import io.a2a.spec.InternalError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Part; import io.a2a.spec.TextPart; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.List; - /** * Producer for the cloud deployment example agent executor. */ @@ -45,7 +46,7 @@ public AgentExecutor agentExecutor() { private static class CloudAgentExecutor implements AgentExecutor { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater updater = new TaskUpdater(context, eventQueue); try { @@ -98,7 +99,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP LOGGER.info("Artifact added on pod: {}", podName); } - } catch (JSONRPCError e) { + } catch (A2AError e) { LOGGER.error("JSONRPC error processing task", e); throw e; } catch (Exception e) { @@ -108,7 +109,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { LOGGER.info("Task cancellation requested"); TaskUpdater updater = new TaskUpdater(context, eventQueue); updater.cancel(); diff --git a/examples/helloworld/client/pom.xml b/examples/helloworld/client/pom.xml index 8f5b63406..2e8a3f3f0 100644 --- a/examples/helloworld/client/pom.xml +++ b/examples/helloworld/client/pom.xml @@ -20,6 +20,11 @@ io.github.a2asdk a2a-java-sdk-client + + io.github.a2asdk + a2a-java-sdk-jsonrpc-common + ${project.version} + diff --git a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java index 413efb03c..c3b1cb473 100644 --- a/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java +++ b/examples/helloworld/client/src/main/java/io/a2a/examples/helloworld/HelloWorldClient.java @@ -16,7 +16,7 @@ import io.a2a.client.http.A2ACardResolver; import io.a2a.client.transport.jsonrpc.JSONRPCTransport; import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfig; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.AgentCard; import io.a2a.spec.Message; import io.a2a.spec.Part; diff --git a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java index 1d7519b60..4bba596db 100644 --- a/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java +++ b/examples/helloworld/server/src/main/java/io/a2a/examples/helloworld/AgentExecutorProducer.java @@ -3,11 +3,11 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; +import io.a2a.A2A; import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; -import io.a2a.A2A; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; import io.a2a.spec.UnsupportedOperationError; @ApplicationScoped @@ -17,12 +17,12 @@ public class AgentExecutorProducer { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { eventQueue.enqueueEvent(A2A.toAgentMessage("Hello World")); } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { throw new UnsupportedOperationError(); } }; diff --git a/extras/push-notification-config-store-database-jpa/pom.xml b/extras/push-notification-config-store-database-jpa/pom.xml index 821eaa5d9..f55cad367 100644 --- a/extras/push-notification-config-store-database-jpa/pom.xml +++ b/extras/push-notification-config-store-database-jpa/pom.xml @@ -22,6 +22,11 @@ ${project.groupId} a2a-java-sdk-server-common + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + jakarta.annotation jakarta.annotation-api diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java index 357cf42e1..ad7b125aa 100644 --- a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java +++ b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStore.java @@ -11,7 +11,7 @@ import jakarta.persistence.PersistenceContext; import jakarta.transaction.Transactional; -import io.a2a.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; diff --git a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java index 225936e47..468f8eddb 100644 --- a/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java +++ b/extras/push-notification-config-store-database-jpa/src/main/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfig.java @@ -6,8 +6,8 @@ import jakarta.persistence.Table; import jakarta.persistence.Transient; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.PushNotificationConfig; @Entity diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java index 6871a0f09..9df56edf8 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreIntegrationTest.java @@ -7,14 +7,14 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; - import java.util.List; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + import io.a2a.client.Client; import io.a2a.client.config.ClientConfig; import io.a2a.client.transport.jsonrpc.JSONRPCTransport; diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java index 3c4242081..df29c1688 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaDatabasePushNotificationConfigStoreTestAgentExecutor.java @@ -11,8 +11,8 @@ import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.PushNotificationSender; import io.a2a.server.tasks.TaskUpdater; +import io.a2a.spec.A2AError; import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Part; import io.a2a.spec.TextPart; @@ -33,7 +33,7 @@ public class JpaDatabasePushNotificationConfigStoreTestAgentExecutor { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); String command = getLastTextPart(context.getMessage()); @@ -55,14 +55,14 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); taskUpdater.cancel(); } }; } - private String getLastTextPart(Message message) throws JSONRPCError { + private String getLastTextPart(Message message) throws A2AError { if (message.parts() == null || message.parts().isEmpty()) { return ""; } diff --git a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java index 1074b7848..6ecf045eb 100644 --- a/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java +++ b/extras/push-notification-config-store-database-jpa/src/test/java/io/a2a/extras/pushnotificationconfigstore/database/jpa/JpaPushNotificationConfigStoreTest.java @@ -11,16 +11,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.mockito.ArgumentCaptor; - import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import jakarta.inject.Inject; import jakarta.transaction.Transactional; @@ -36,6 +28,12 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; @QuarkusTest public class JpaPushNotificationConfigStoreTest { diff --git a/extras/queue-manager-replicated/core/pom.xml b/extras/queue-manager-replicated/core/pom.xml index c5d1ee8bf..cdc6da7e9 100644 --- a/extras/queue-manager-replicated/core/pom.xml +++ b/extras/queue-manager-replicated/core/pom.xml @@ -20,6 +20,11 @@ a2a-java-sdk-server-common ${project.version} + + io.github.a2asdk + a2a-java-sdk-jsonrpc-common + ${project.version} + io.github.a2asdk a2a-java-extras-common diff --git a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java index 5eac92d4f..30527b797 100644 --- a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java +++ b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedEventQueueItem.java @@ -4,10 +4,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonSetter; - import io.a2a.server.events.EventQueueItem; +import io.a2a.spec.A2AError; import io.a2a.spec.Event; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.StreamingEventKind; public class ReplicatedEventQueueItem implements EventQueueItem { @@ -17,7 +16,7 @@ public class ReplicatedEventQueueItem implements EventQueueItem { private StreamingEventKind event; @JsonInclude(JsonInclude.Include.NON_NULL) - private JSONRPCError error; + private A2AError error; private boolean closedEvent; @@ -32,8 +31,8 @@ public ReplicatedEventQueueItem(String taskId, StreamingEventKind event) { this.error = null; } - // Constructor for creating from A2A JSONRPCError objects - public ReplicatedEventQueueItem(String taskId, JSONRPCError error) { + // Constructor for creating from A2A A2AError objects + public ReplicatedEventQueueItem(String taskId, A2AError error) { this.taskId = taskId; this.event = null; this.error = error; @@ -50,12 +49,12 @@ public ReplicatedEventQueueItem(String taskId, Event event) { this.event = streamingEvent; this.error = null; this.closedEvent = false; - } else if (event instanceof JSONRPCError jsonRpcError) { + } else if (event instanceof A2AError jsonRpcError) { this.event = null; this.error = jsonRpcError; this.closedEvent = false; } else { - throw new IllegalArgumentException("Event must be StreamingEventKind, JSONRPCError, or QueueClosedEvent, got: " + event.getClass()); + throw new IllegalArgumentException("Event must be StreamingEventKind, A2AError, or QueueClosedEvent, got: " + event.getClass()); } } @@ -85,17 +84,17 @@ public void setEvent(StreamingEventKind event) { } /** - * Get the JSONRPCError field (for JSON serialization). - * @return the JSONRPCError or null + * Get the A2AError field (for JSON serialization). + * @return the A2AError or null */ @JsonGetter("error") @JsonInclude(JsonInclude.Include.NON_NULL) - public JSONRPCError getErrorObject() { + public A2AError getErrorObject() { return error; } @JsonSetter("error") - public void setError(JSONRPCError error) { + public void setError(A2AError error) { this.error = error; this.event = null; // Clear event when setting error } @@ -103,7 +102,7 @@ public void setError(JSONRPCError error) { /** * Get the contained event as the generic Event interface (implements EventQueueItem). * This is the method required by the EventQueueItem interface. - * @return the event (StreamingEventKind, JSONRPCError, or QueueClosedEvent) or null if none is set + * @return the event (StreamingEventKind, A2AError, or QueueClosedEvent) or null if none is set */ @JsonIgnore @Override @@ -137,7 +136,7 @@ public boolean hasEvent() { /** * Check if this ReplicatedEvent contains an error. - * @return true if it contains a JSONRPCError + * @return true if it contains a A2AError */ public boolean hasError() { return error != null; diff --git a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java index 5e90ed00d..88c0c75ab 100644 --- a/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java +++ b/extras/queue-manager-replicated/core/src/main/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManager.java @@ -7,17 +7,16 @@ import jakarta.enterprise.inject.Alternative; import jakarta.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import io.a2a.extras.common.events.TaskFinalizedEvent; -import io.a2a.server.tasks.TaskStateProvider; import io.a2a.server.events.EventEnqueueHook; import io.a2a.server.events.EventQueue; import io.a2a.server.events.EventQueueFactory; import io.a2a.server.events.EventQueueItem; import io.a2a.server.events.InMemoryQueueManager; import io.a2a.server.events.QueueManager; +import io.a2a.server.tasks.TaskStateProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @ApplicationScoped @Alternative diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java index ae2679bdc..ca781b5b0 100644 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java +++ b/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/EventSerializationTest.java @@ -9,15 +9,16 @@ import java.util.List; -import io.a2a.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.events.QueueClosedEvent; +import io.a2a.spec.A2AError; import io.a2a.spec.Artifact; import io.a2a.spec.Event; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.Part; @@ -32,12 +33,11 @@ import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.json.JsonUtil; import org.junit.jupiter.api.Test; /** * Comprehensive test for serialization/deserialization of all StreamingEventKind classes - * and JSONRPCError subclasses to ensure proper type handling in replication. + * and A2AError subclasses to ensure proper type handling in replication. */ public class EventSerializationTest { @@ -169,9 +169,9 @@ public void testTaskArtifactUpdateEventSerialization() throws JsonProcessingExce } @Test - public void testJSONRPCErrorSubclassesSerialization() throws JsonProcessingException { - // Test various JSONRPCError subclasses - JSONRPCError[] errors = { + public void testA2AErrorSubclassesSerialization() throws JsonProcessingException { + // Test various A2AError subclasses + A2AError[] errors = { new InvalidRequestError("Invalid request"), new MethodNotFoundError(), new InvalidParamsError("Invalid params"), @@ -184,13 +184,13 @@ public void testJSONRPCErrorSubclassesSerialization() throws JsonProcessingExcep // Note: ContentTypeNotSupportedError and InvalidAgentResponseError need specific constructor parameters }; - for (JSONRPCError originalError : errors) { + for (A2AError originalError : errors) { // Test serialization String json = JsonUtil.toJson(originalError); assertTrue(json.contains("\"message\""), "JSON should contain error message for " + originalError.getClass().getSimpleName()); - // Test deserialization - it's acceptable to deserialize as base JSONRPCError - JSONRPCError deserializedError = JsonUtil.fromJson(json, JSONRPCError.class); + // Test deserialization - it's acceptable to deserialize as base A2AError + A2AError deserializedError = JsonUtil.fromJson(json, A2AError.class); assertNotNull(deserializedError, "Should deserialize successfully for " + originalError.getClass().getSimpleName()); assertEquals(originalError.getMessage(), deserializedError.getMessage(), "Error message should match for " + originalError.getClass().getSimpleName()); assertEquals(originalError.getCode(), deserializedError.getCode(), "Error code should match for " + originalError.getClass().getSimpleName()); @@ -243,10 +243,10 @@ public void testReplicatedEventWithStreamingEventSerialization() throws JsonProc @Test public void testReplicatedEventWithErrorSerialization() throws JsonProcessingException { - // Test that ReplicatedEventQueueItem can properly handle JSONRPCError + // Test that ReplicatedEventQueueItem can properly handle A2AError InvalidRequestError error = new InvalidRequestError("Invalid request for testing"); - // Create ReplicatedEventQueueItem with JSONRPCError + // Create ReplicatedEventQueueItem with A2AError ReplicatedEventQueueItem originalReplicatedEvent = new ReplicatedEventQueueItem("error-test-task", error); // Serialize the ReplicatedEventQueueItemQueueItem @@ -261,7 +261,7 @@ public void testReplicatedEventWithErrorSerialization() throws JsonProcessingExc assertEquals(originalReplicatedEvent.getTaskId(), deserializedReplicatedEvent.getTaskId()); // Should get the error back - JSONRPCError retrievedError = deserializedReplicatedEvent.getErrorObject(); + A2AError retrievedError = deserializedReplicatedEvent.getErrorObject(); assertNotNull(retrievedError); assertEquals(error.getMessage(), retrievedError.getMessage()); assertEquals(error.getCode(), retrievedError.getCode()); diff --git a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java b/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java index 0a9326ea0..43571cd30 100644 --- a/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java +++ b/extras/queue-manager-replicated/core/src/test/java/io/a2a/extras/queuemanager/replicated/core/ReplicatedQueueManagerTest.java @@ -17,6 +17,7 @@ import java.util.concurrent.atomic.AtomicInteger; import io.a2a.extras.common.events.TaskFinalizedEvent; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.events.EventQueue; import io.a2a.server.events.EventQueueClosedException; import io.a2a.server.events.EventQueueItem; @@ -27,7 +28,6 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.json.JsonUtil; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml index 77f51477d..2508821b6 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/pom.xml +++ b/extras/queue-manager-replicated/replication-mp-reactive/pom.xml @@ -20,6 +20,11 @@ a2a-java-queue-manager-replicated-core ${project.version} + + io.github.a2asdk + a2a-java-sdk-jsonrpc-common + ${project.version} + io.quarkus quarkus-messaging diff --git a/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java b/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java index 26797bc5f..6f0ca9876 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java +++ b/extras/queue-manager-replicated/replication-mp-reactive/src/main/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategy.java @@ -6,7 +6,7 @@ import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; import io.a2a.extras.queuemanager.replicated.core.ReplicationStrategy; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonUtil; import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; import org.eclipse.microprofile.reactive.messaging.Incoming; diff --git a/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java b/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java index 593371f28..4638f7385 100644 --- a/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java +++ b/extras/queue-manager-replicated/replication-mp-reactive/src/test/java/io/a2a/extras/queuemanager/replicated/mp_reactive/ReactiveMessagingReplicationStrategyTest.java @@ -1,11 +1,21 @@ package io.a2a.extras.queuemanager.replicated.mp_reactive; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import jakarta.enterprise.event.Event; +import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatus; +import io.a2a.spec.TaskStatusUpdateEvent; import org.eclipse.microprofile.reactive.messaging.Emitter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -14,13 +24,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.spec.StreamingEventKind; -import io.a2a.spec.TaskStatus; -import io.a2a.spec.TaskState; -import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.json.JsonUtil; - @ExtendWith(MockitoExtension.class) class ReactiveMessagingReplicationStrategyTest { diff --git a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java index 51aa7ac0c..546d22939 100644 --- a/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java +++ b/extras/queue-manager-replicated/tests-multi-instance/quarkus-common/src/main/java/io/a2a/extras/queuemanager/replicated/tests/multiinstance/common/MultiInstanceReplicationAgentExecutor.java @@ -4,7 +4,7 @@ import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; import io.a2a.spec.Task; import io.a2a.spec.TextPart; @@ -18,7 +18,7 @@ */ public class MultiInstanceReplicationAgentExecutor implements AgentExecutor { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { Task task = context.getTask(); TaskUpdater updater = new TaskUpdater(context, eventQueue); @@ -41,7 +41,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater updater = new TaskUpdater(context, eventQueue); updater.cancel(); } diff --git a/extras/queue-manager-replicated/tests-single-instance/pom.xml b/extras/queue-manager-replicated/tests-single-instance/pom.xml index b92043be6..29cca7256 100644 --- a/extras/queue-manager-replicated/tests-single-instance/pom.xml +++ b/extras/queue-manager-replicated/tests-single-instance/pom.xml @@ -25,6 +25,11 @@ a2a-java-queue-manager-replication-mp-reactive ${project.version} + + io.github.a2asdk + a2a-java-sdk-jsonrpc-common + ${project.version} + diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java index f174303ac..3825f3bad 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/KafkaReplicationIntegrationTest.java @@ -28,6 +28,7 @@ import io.a2a.client.transport.jsonrpc.JSONRPCTransport; import io.a2a.client.transport.jsonrpc.JSONRPCTransportConfigBuilder; import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.PublicAgentCard; import io.a2a.server.events.QueueClosedEvent; import io.a2a.spec.A2AClientException; @@ -39,7 +40,6 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; -import io.a2a.json.JsonUtil; import io.quarkus.test.junit.QuarkusTest; import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java index 83642b183..547a731fd 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicatedQueueManagerTest.java @@ -1,14 +1,13 @@ package io.a2a.extras.queuemanager.replicated.tests; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import jakarta.inject.Inject; -import org.junit.jupiter.api.Test; - import io.a2a.extras.queuemanager.replicated.core.ReplicatedQueueManager; import io.a2a.server.events.QueueManager; import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; /** * Basic test to verify the ReplicatedQueueManager is properly configured. diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java index 603857ef1..8e4db21dd 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/ReplicationTestAgentExecutor.java @@ -9,8 +9,8 @@ import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; +import io.a2a.spec.A2AError; import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Part; import io.a2a.spec.TextPart; @@ -28,7 +28,7 @@ public class ReplicationTestAgentExecutor { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); String lastText = getLastTextPart(context.getMessage()); @@ -56,14 +56,14 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); taskUpdater.cancel(); } }; } - private String getLastTextPart(Message message) throws JSONRPCError { + private String getLastTextPart(Message message) throws A2AError { if (message.parts().isEmpty()) { throw new InvalidRequestError("No parts in message"); } diff --git a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java index 9e308ec42..a7edd13d3 100644 --- a/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java +++ b/extras/queue-manager-replicated/tests-single-instance/src/test/java/io/a2a/extras/queuemanager/replicated/tests/TestKafkaEventConsumer.java @@ -6,11 +6,10 @@ import jakarta.enterprise.context.ApplicationScoped; -import org.eclipse.microprofile.reactive.messaging.Incoming; - import io.a2a.extras.queuemanager.replicated.core.ReplicatedEventQueueItem; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.quarkus.arc.profile.IfBuildProfile; +import org.eclipse.microprofile.reactive.messaging.Incoming; /** * Test consumer for Kafka replicated events using reactive messaging. diff --git a/extras/task-store-database-jpa/pom.xml b/extras/task-store-database-jpa/pom.xml index 3f5aee4f1..7c3c37062 100644 --- a/extras/task-store-database-jpa/pom.xml +++ b/extras/task-store-database-jpa/pom.xml @@ -22,6 +22,11 @@ ${project.groupId} a2a-java-sdk-server-common + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-extras-common diff --git a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java b/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java index df65f290e..49dad1728 100644 --- a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java +++ b/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStore.java @@ -16,14 +16,14 @@ import jakarta.persistence.TypedQuery; import jakarta.transaction.Transactional; -import io.a2a.json.JsonProcessingException; import io.a2a.extras.common.events.TaskFinalizedEvent; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.config.A2AConfigProvider; import io.a2a.server.tasks.TaskStateProvider; import io.a2a.server.tasks.TaskStore; import io.a2a.spec.Artifact; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.Task; import org.slf4j.Logger; diff --git a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java b/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java index 3aabad9d7..021a693e3 100644 --- a/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java +++ b/extras/task-store-database-jpa/src/main/java/io/a2a/extras/taskstore/database/jpa/JpaTask.java @@ -8,8 +8,8 @@ import jakarta.persistence.Table; import jakarta.persistence.Transient; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.Task; @Entity diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java index cfb4eadc8..ea77f73c7 100644 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java +++ b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTest.java @@ -15,10 +15,10 @@ import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.tasks.TaskStore; import io.a2a.spec.Artifact; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskState; diff --git a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java index 58e52e57d..f3b310750 100644 --- a/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java +++ b/extras/task-store-database-jpa/src/test/java/io/a2a/extras/taskstore/database/jpa/JpaDatabaseTaskStoreTestAgentExecutor.java @@ -9,8 +9,8 @@ import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; +import io.a2a.spec.A2AError; import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Part; import io.a2a.spec.TextPart; @@ -28,7 +28,7 @@ public class JpaDatabaseTaskStoreTestAgentExecutor { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { System.out.println("TestAgentExecutor.execute() called for task: " + context.getTaskId()); System.out.println("Message " + context.getMessage()); @@ -47,14 +47,14 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); taskUpdater.cancel(); } }; } - private String getLastTextPart(Message message) throws JSONRPCError { + private String getLastTextPart(Message message) throws A2AError { Part part = message.parts().get(message.parts().size() - 1); if (part instanceof TextPart) { return ((TextPart) part).text(); diff --git a/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java b/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java index 0aba695ff..6d2e5f55f 100644 --- a/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java +++ b/http-client/src/main/java/io/a2a/client/http/A2ACardResolver.java @@ -8,11 +8,11 @@ import io.a2a.grpc.utils.JSONRPCUtils; import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.spec.A2AClientError; import io.a2a.spec.A2AClientJSONError; import io.a2a.spec.AgentCard; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; import org.jspecify.annotations.Nullable; import static io.a2a.util.Assert.checkNotNullParam; @@ -135,9 +135,9 @@ public AgentCard getAgentCard() throws A2AClientError, A2AClientJSONError { try { io.a2a.grpc.AgentCard.Builder agentCardBuilder = io.a2a.grpc.AgentCard.newBuilder(); - JSONRPCUtils.parseJsonString(body, agentCardBuilder, null); + JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); return ProtoUtils.FromProto.agentCard(agentCardBuilder); - } catch (JSONRPCError | JsonProcessingException e) { + } catch (A2AError | JsonProcessingException e) { throw new A2AClientJSONError("Could not unmarshal agent card response", e); } } diff --git a/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java b/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java index 242001d10..3254992ef 100644 --- a/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java +++ b/http-client/src/test/java/io/a2a/client/http/A2ACardResolverTest.java @@ -12,7 +12,7 @@ import com.google.protobuf.util.JsonFormat; import io.a2a.grpc.utils.JSONRPCUtils; import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.spec.A2AClientError; import io.a2a.spec.A2AClientJSONError; import io.a2a.spec.AgentCard; @@ -82,7 +82,7 @@ public void testGetAgentCardSuccess() throws Exception { private AgentCard unmarshalFrom(String body) throws JsonProcessingException { io.a2a.grpc.AgentCard.Builder agentCardBuilder = io.a2a.grpc.AgentCard.newBuilder(); - JSONRPCUtils.parseJsonString(body, agentCardBuilder, null); + JSONRPCUtils.parseJsonString(body, agentCardBuilder, ""); return ProtoUtils.FromProto.agentCard(agentCardBuilder); } diff --git a/jsonrpc-common/pom.xml b/jsonrpc-common/pom.xml new file mode 100644 index 000000000..f566ad9a3 --- /dev/null +++ b/jsonrpc-common/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + io.github.a2asdk + a2a-java-sdk-parent + 0.4.0.Alpha1-SNAPSHOT + + a2a-java-sdk-jsonrpc-common + + jar + + Java SDK A2A JSONRPC Common + Java SDK for the Agent2Agent Protocol (A2A) - Internal implementation utilities (not part of public API) + + + + ${project.groupId} + a2a-java-sdk-spec + + + com.google.code.gson + gson + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + + diff --git a/spec/src/main/java/io/a2a/spec/IdJsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java similarity index 92% rename from spec/src/main/java/io/a2a/spec/IdJsonMappingException.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java index 6d0e1692f..de56d119c 100644 --- a/spec/src/main/java/io/a2a/spec/IdJsonMappingException.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/IdJsonMappingException.java @@ -1,6 +1,4 @@ -package io.a2a.spec; - -import io.a2a.json.JsonMappingException; +package io.a2a.jsonrpc.common.json; /** * JSON mapping exception that includes request ID for error tracking. @@ -10,7 +8,7 @@ public class IdJsonMappingException extends JsonMappingException { /** * The JSON-RPC request ID associated with this exception. */ - Object id; + private Object id; /** * Constructs exception with message and ID. diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java similarity index 95% rename from spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java index a3917effb..5ac8c769c 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsJsonMappingException.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/InvalidParamsJsonMappingException.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.json; /** * Exception for invalid parameters during JSON mapping. diff --git a/spec/src/main/java/io/a2a/json/JsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java similarity index 99% rename from spec/src/main/java/io/a2a/json/JsonMappingException.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java index 8d3ad48e7..dc85d6edb 100644 --- a/spec/src/main/java/io/a2a/json/JsonMappingException.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonMappingException.java @@ -1,4 +1,4 @@ -package io.a2a.json; +package io.a2a.jsonrpc.common.json; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/json/JsonProcessingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java similarity index 97% rename from spec/src/main/java/io/a2a/json/JsonProcessingException.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java index 9af50b7ce..cdbb7b4eb 100644 --- a/spec/src/main/java/io/a2a/json/JsonProcessingException.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonProcessingException.java @@ -1,4 +1,4 @@ -package io.a2a.json; +package io.a2a.jsonrpc.common.json; import org.jspecify.annotations.Nullable; diff --git a/spec/src/main/java/io/a2a/json/JsonUtil.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java similarity index 97% rename from spec/src/main/java/io/a2a/json/JsonUtil.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java index ddd712a43..c6de924bf 100644 --- a/spec/src/main/java/io/a2a/json/JsonUtil.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/JsonUtil.java @@ -1,5 +1,6 @@ -package io.a2a.json; +package io.a2a.jsonrpc.common.json; +import static io.a2a.jsonrpc.common.json.JsonUtil.A2AErrorTypeAdapter.THROWABLE_MARKER_FIELD; import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; @@ -12,6 +13,13 @@ import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; +import java.io.StringReader; +import java.lang.reflect.Type; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Map; + import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; @@ -21,6 +29,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; +import io.a2a.spec.A2AError; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DataPart; import io.a2a.spec.FileContent; @@ -31,7 +40,6 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.Part; @@ -45,16 +53,8 @@ import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; -import java.io.StringReader; -import java.lang.reflect.Type; -import java.util.Map; -import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; import org.jspecify.annotations.Nullable; -import static io.a2a.json.JsonUtil.JSONRPCErrorTypeAdapter.THROWABLE_MARKER_FIELD; - /** * Utility class for JSON operations. */ @@ -64,7 +64,7 @@ private static GsonBuilder createBaseGsonBuilder() { return new GsonBuilder() .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()) - .registerTypeHierarchyAdapter(JSONRPCError.class, new JSONRPCErrorTypeAdapter()) + .registerTypeHierarchyAdapter(A2AError.class, new A2AErrorTypeAdapter()) .registerTypeAdapter(TaskState.class, new TaskStateTypeAdapter()) .registerTypeAdapter(Message.Role.class, new RoleTypeAdapter()) .registerTypeHierarchyAdapter(FileContent.class, new FileContentTypeAdapter()); @@ -261,7 +261,7 @@ Throwable read(JsonReader in) throws java.io.IOException { } /** - * Gson TypeAdapter for serializing and deserializing {@link JSONRPCError} and its subclasses. + * Gson TypeAdapter for serializing and deserializing {@link A2AError} and its subclasses. *

* This adapter handles polymorphic deserialization based on the error code, creating the * appropriate subclass instance. @@ -279,12 +279,12 @@ Throwable read(JsonReader in) throws java.io.IOException { *

  • -32004: {@link UnsupportedOperationError}
  • *
  • -32005: {@link ContentTypeNotSupportedError}
  • *
  • -32006: {@link InvalidAgentResponseError}
  • - *
  • Other codes: {@link JSONRPCError}
  • + *
  • Other codes: {@link A2AError}
  • * * - * @see JSONRPCError + * @see A2AError */ - static class JSONRPCErrorTypeAdapter extends TypeAdapter { + static class A2AErrorTypeAdapter extends TypeAdapter { private static final ThrowableTypeAdapter THROWABLE_ADAPTER = new ThrowableTypeAdapter(); static final String THROWABLE_MARKER_FIELD = "__throwable"; @@ -294,7 +294,7 @@ static class JSONRPCErrorTypeAdapter extends TypeAdapter { private static final String TYPE_FIELD = "type"; @Override - public void write(JsonWriter out, JSONRPCError value) throws java.io.IOException { + public void write(JsonWriter out, A2AError value) throws java.io.IOException { if (value == null) { out.nullValue(); return; @@ -317,7 +317,7 @@ public void write(JsonWriter out, JSONRPCError value) throws java.io.IOException @Override public @Nullable - JSONRPCError read(JsonReader in) throws java.io.IOException { + A2AError read(JsonReader in) throws java.io.IOException { if (in.peek() == com.google.gson.stream.JsonToken.NULL) { in.nextNull(); return null; @@ -390,11 +390,11 @@ Object readDataValue(JsonReader in) throws java.io.IOException { } /** - * Creates the appropriate JSONRPCError subclass based on the error code. + * Creates the appropriate A2AError subclass based on the error code. */ - private JSONRPCError createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { + private A2AError createErrorInstance(@Nullable Integer code, @Nullable String message, @Nullable Object data) { if (code == null) { - throw new JsonSyntaxException("JSONRPCError must have a code field"); + throw new JsonSyntaxException("A2AError must have a code field"); } return switch (code) { @@ -421,7 +421,7 @@ private JSONRPCError createErrorInstance(@Nullable Integer code, @Nullable Strin case INVALID_AGENT_RESPONSE_ERROR_CODE -> new InvalidAgentResponseError(code, message, data); default -> - new JSONRPCError(code, message, data); + new A2AError(code, message, data); }; } } diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java similarity index 93% rename from spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java index dc1f13c03..5bac1c026 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundJsonMappingException.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/MethodNotFoundJsonMappingException.java @@ -1,4 +1,6 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.json; + +import io.a2a.spec.MethodNotFoundError; /** * Exception thrown when JSON mapping fails due to a method not found error. diff --git a/spec/src/main/java/io/a2a/json/package-info.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java similarity index 88% rename from spec/src/main/java/io/a2a/json/package-info.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java index 81fe05a3a..e6f547b92 100644 --- a/spec/src/main/java/io/a2a/json/package-info.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/json/package-info.java @@ -5,4 +5,4 @@ * allowing the SDK to be independent of any specific JSON library implementation. */ @org.jspecify.annotations.NullMarked -package io.a2a.json; +package io.a2a.jsonrpc.common.json; diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java similarity index 81% rename from spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java index 445b6f330..e2f91c35a 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCErrorResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AErrorResponse.java @@ -1,5 +1,6 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; +import io.a2a.spec.A2AError; import io.a2a.util.Assert; /** @@ -9,18 +10,18 @@ * According to the JSON-RPC 2.0 specification, an error response must contain: *
      *
    • {@code jsonrpc} - Always "2.0"
    • - *
    • {@code error} - A {@link JSONRPCError} object describing the error
    • + *
    • {@code error} - A {@link A2AError} object describing the error
    • *
    • {@code id} - The request ID, or null if the ID could not be determined
    • *
    *

    * The {@code result} field must be absent or null in error responses. This class * enforces that constraint by fixing the result type parameter to {@code Void}. * - * @see JSONRPCError - * @see JSONRPCResponse + * @see A2AError + * @see A2AResponse * @see JSON-RPC 2.0 Response Object */ -public final class JSONRPCErrorResponse extends JSONRPCResponse { +public final class A2AErrorResponse extends A2AResponse { /** * Constructs a JSON-RPC error response with all fields. @@ -33,7 +34,7 @@ public final class JSONRPCErrorResponse extends JSONRPCResponse { * @param error the error object describing what went wrong (required) * @throws IllegalArgumentException if error is null */ - public JSONRPCErrorResponse(String jsonrpc, Object id, Void result, JSONRPCError error) { + public A2AErrorResponse(String jsonrpc, Object id, Void result, A2AError error) { super(jsonrpc, id, result, error, Void.class); Assert.checkNotNullParam("error", error); } @@ -46,7 +47,7 @@ public JSONRPCErrorResponse(String jsonrpc, Object id, Void result, JSONRPCError * @param id the request ID * @param error the error object (required) */ - public JSONRPCErrorResponse(Object id, JSONRPCError error) { + public A2AErrorResponse(Object id, A2AError error) { this(null, id, null, error); } @@ -58,7 +59,7 @@ public JSONRPCErrorResponse(Object id, JSONRPCError error) { * * @param error the error object (required) */ - public JSONRPCErrorResponse(JSONRPCError error) { + public A2AErrorResponse(A2AError error) { this(null, null, null, error); } } diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCMessage.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java similarity index 86% rename from spec/src/main/java/io/a2a/spec/JSONRPCMessage.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java index f3b8ed5fa..183b8359f 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCMessage.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AMessage.java @@ -1,23 +1,23 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; /** * Base interface for all JSON-RPC 2.0 protocol messages in the A2A Protocol. *

    * This sealed interface defines the fundamental structure shared by all JSON-RPC 2.0 * messages used in the A2A Protocol's JSON-RPC transport layer. It ensures type safety - * and exhaustiveness checking by permitting only {@link JSONRPCRequest} and {@link JSONRPCResponse} + * and exhaustiveness checking by permitting only {@link A2ARequest} and {@link A2AResponse} * as implementing types. *

    * According to the JSON-RPC 2.0 specification, all messages must include a {@code jsonrpc} * version field set to "2.0", and may optionally include an {@code id} field for correlation * between requests and responses. * - * @see JSONRPCRequest - * @see JSONRPCResponse + * @see A2ARequest + * @see A2AResponse * @see JSON-RPC 2.0 Specification * @see A2A Protocol Specification */ -public sealed interface JSONRPCMessage permits JSONRPCRequest, JSONRPCResponse { +public sealed interface A2AMessage permits A2ARequest, A2AResponse { /** * The JSON-RPC protocol version string as defined by the JSON-RPC 2.0 specification. diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/JSONRPCRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java index b09d445e5..e7200219a 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2ARequest.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; import io.a2a.util.Assert; import io.a2a.util.Utils; @@ -28,7 +28,7 @@ * @see JSON-RPC 2.0 Specification * @see A2A Protocol Specification */ -public abstract sealed class JSONRPCRequest implements JSONRPCMessage permits NonStreamingJSONRPCRequest, StreamingJSONRPCRequest { +public abstract sealed class A2ARequest implements A2AMessage permits NonStreamingJSONRPCRequest, StreamingJSONRPCRequest { /** The JSON-RPC protocol version. */ protected String jsonrpc; @@ -45,7 +45,7 @@ public abstract sealed class JSONRPCRequest implements JSONRPCMessage permits /** * Default constructor for JSON deserialization. */ - public JSONRPCRequest() { + public A2ARequest() { } /** diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java similarity index 74% rename from spec/src/main/java/io/a2a/spec/JSONRPCResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java index 3c6685939..73bb430eb 100644 --- a/spec/src/main/java/io/a2a/spec/JSONRPCResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/A2AResponse.java @@ -1,7 +1,8 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; import static io.a2a.util.Utils.defaultIfNull; +import io.a2a.spec.A2AError; import io.a2a.util.Assert; /** @@ -9,7 +10,7 @@ * * @param the type of the result value returned in successful responses */ -public abstract sealed class JSONRPCResponse implements JSONRPCMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetAuthenticatedExtendedCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, JSONRPCErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, SetTaskPushNotificationConfigResponse { +public abstract sealed class A2AResponse implements A2AMessage permits CancelTaskResponse, DeleteTaskPushNotificationConfigResponse, GetAuthenticatedExtendedCardResponse, GetTaskPushNotificationConfigResponse, GetTaskResponse, A2AErrorResponse, ListTaskPushNotificationConfigResponse, ListTasksResponse, SendMessageResponse, SendStreamingMessageResponse, SetTaskPushNotificationConfigResponse { /** The JSON-RPC protocol version. */ protected String jsonrpc; @@ -18,12 +19,12 @@ public abstract sealed class JSONRPCResponse implements JSONRPCMessage permit /** The result of the method invocation. */ protected T result; /** The error object if the invocation failed. */ - protected JSONRPCError error; + protected A2AError error; /** * Default constructor for deserialization. */ - public JSONRPCResponse() { + public A2AResponse() { } /** @@ -35,7 +36,7 @@ public JSONRPCResponse() { * @param error the error if any * @param resultType the result type class */ - public JSONRPCResponse(String jsonrpc, Object id, T result, JSONRPCError error, Class resultType) { + public A2AResponse(String jsonrpc, Object id, T result, A2AError error, Class resultType) { if (jsonrpc != null && ! jsonrpc.equals(JSONRPC_VERSION)) { throw new IllegalArgumentException("Invalid JSON-RPC protocol version"); } @@ -76,7 +77,7 @@ public T getResult() { * * @return the error if any */ - public JSONRPCError getError() { + public A2AError getError() { return this.error; } } diff --git a/spec/src/main/java/io/a2a/spec/CancelTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/CancelTaskRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java index e2667fc45..836cb6e06 100644 --- a/spec/src/main/java/io/a2a/spec/CancelTaskRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/CancelTaskRequest.java @@ -1,7 +1,13 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; import java.util.UUID; +import io.a2a.spec.TaskIdParams; +import io.a2a.spec.TaskNotCancelableError; +import io.a2a.spec.TaskState; + /** * JSON-RPC request to cancel an in-progress task. *

    @@ -21,9 +27,6 @@ */ public final class CancelTaskRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name for canceling tasks. */ - public static final String METHOD = "CancelTask"; - /** * Creates a new CancelTaskRequest with the specified JSON-RPC parameters. * @@ -33,7 +36,7 @@ public final class CancelTaskRequest extends NonStreamingJSONRPCRequest * If the task cannot be canceled (e.g., already completed) or is not found, the error - * field will contain a {@link JSONRPCError} such as {@link TaskNotCancelableError} or + * field will contain a {@link io.a2a.spec.A2AError} such as {@link TaskNotCancelableError} or * {@link TaskNotFoundError}. * * @see CancelTaskRequest for the corresponding request @@ -16,7 +22,7 @@ * @see A2A Protocol Specification */ -public final class CancelTaskResponse extends JSONRPCResponse { +public final class CancelTaskResponse extends A2AResponse { /** * Constructs a CancelTaskResponse with full parameters. @@ -26,7 +32,7 @@ public final class CancelTaskResponse extends JSONRPCResponse { * @param result the task result * @param error the error if any */ - public CancelTaskResponse(String jsonrpc, Object id, Task result, JSONRPCError error) { + public CancelTaskResponse(String jsonrpc, Object id, Task result, A2AError error) { super(jsonrpc, id, result, error, Task.class); } @@ -36,7 +42,7 @@ public CancelTaskResponse(String jsonrpc, Object id, Task result, JSONRPCError e * @param id the request ID * @param error the error */ - public CancelTaskResponse(Object id, JSONRPCError error) { + public CancelTaskResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java similarity index 94% rename from spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java index 9fcf3ace3..64f983520 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + import java.util.UUID; +import io.a2a.spec.DeleteTaskPushNotificationConfigParams; + +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; + /** * JSON-RPC request to delete a push notification configuration from a task. *

    @@ -17,9 +22,6 @@ */ public final class DeleteTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name for deleting push notification configurations. */ - public static final String METHOD = "DeleteTaskPushNotificationConfig"; - /** * Creates a new DeleteTaskPushNotificationConfigRequest with the specified JSON-RPC parameters. * @@ -29,7 +31,7 @@ public final class DeleteTaskPushNotificationConfigRequest extends NonStreamingJ * @throws IllegalArgumentException if jsonrpc version is invalid, method is not "DeleteTaskPushNotificationConfig", or id is not a string/integer/null */ public DeleteTaskPushNotificationConfigRequest(String jsonrpc, Object id, DeleteTaskPushNotificationConfigParams params) { - super(jsonrpc, METHOD, id, params); + super(jsonrpc, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); } /** diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java similarity index 86% rename from spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java index 296e1dc28..d25674814 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/DeleteTaskPushNotificationConfigResponse.java @@ -1,4 +1,6 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.A2AError; /** * JSON-RPC response confirming deletion of a task's push notification configuration. @@ -6,12 +8,12 @@ * This response confirms successful deletion of the push notification configuration. * The result is void (no content) on success. *

    - * If an error occurs during deletion, the error field will contain a {@link JSONRPCError}. + * If an error occurs during deletion, the error field will contain a {@link A2AError}. * * @see DeleteTaskPushNotificationConfigRequest for the corresponding request * @see A2A Protocol Specification */ -public final class DeleteTaskPushNotificationConfigResponse extends JSONRPCResponse { +public final class DeleteTaskPushNotificationConfigResponse extends A2AResponse { /** * Creates a new DeleteTaskPushNotificationConfigResponse with full JSON-RPC parameters. @@ -21,7 +23,7 @@ public final class DeleteTaskPushNotificationConfigResponse extends JSONRPCRespo * @param result the result (always null/Void for this response type) * @param error the error if the request failed, null on success */ - public DeleteTaskPushNotificationConfigResponse(String jsonrpc, Object id, Void result,JSONRPCError error) { + public DeleteTaskPushNotificationConfigResponse(String jsonrpc, Object id, Void result,A2AError error) { super(jsonrpc, id, result, error, Void.class); } @@ -31,7 +33,7 @@ public DeleteTaskPushNotificationConfigResponse(String jsonrpc, Object id, Void * @param id the response identifier matching the request * @param error the error describing why the deletion failed */ - public DeleteTaskPushNotificationConfigResponse(Object id, JSONRPCError error) { + public DeleteTaskPushNotificationConfigResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/GetAuthenticatedExtendedCardRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardRequest.java similarity index 92% rename from spec/src/main/java/io/a2a/spec/GetAuthenticatedExtendedCardRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardRequest.java index 894c3510e..5fb2f00bb 100644 --- a/spec/src/main/java/io/a2a/spec/GetAuthenticatedExtendedCardRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; import java.util.UUID; +import io.a2a.spec.AgentCard; +import io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError; + /** * JSON-RPC request to retrieve an agent's extended card with authenticated details. *

    @@ -28,9 +33,6 @@ */ public final class GetAuthenticatedExtendedCardRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name for getting extended agent card. */ - public static final String METHOD = "GetExtendedAgentCard"; - /** * Constructs request with full parameters. * @@ -38,7 +40,7 @@ public final class GetAuthenticatedExtendedCardRequest extends NonStreamingJSONR * @param id the request ID */ public GetAuthenticatedExtendedCardRequest(String jsonrpc, Object id) { - super(jsonrpc, METHOD, id); + super(jsonrpc, GET_EXTENDED_AGENT_CARD_METHOD, id); } /** diff --git a/spec/src/main/java/io/a2a/spec/GetAuthenticatedExtendedCardResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardResponse.java similarity index 81% rename from spec/src/main/java/io/a2a/spec/GetAuthenticatedExtendedCardResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardResponse.java index ea82af58e..41e5c238b 100644 --- a/spec/src/main/java/io/a2a/spec/GetAuthenticatedExtendedCardResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetAuthenticatedExtendedCardResponse.java @@ -1,4 +1,8 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.A2AError; +import io.a2a.spec.AgentCard; +import io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError; /** * JSON-RPC response containing an agent's extended card with authenticated details. @@ -8,7 +12,7 @@ * security configurations, or other authenticated-only capabilities. *

    * If the agent doesn't support authenticated extended cards or authentication fails, - * the error field will contain a {@link JSONRPCError} such as + * the error field will contain a {@link A2AError} such as * {@link AuthenticatedExtendedCardNotConfiguredError}. * * @see GetAuthenticatedExtendedCardRequest for the corresponding request @@ -16,7 +20,7 @@ * @see AuthenticatedExtendedCardNotConfiguredError for the error when unsupported * @see A2A Protocol Specification */ -public final class GetAuthenticatedExtendedCardResponse extends JSONRPCResponse { +public final class GetAuthenticatedExtendedCardResponse extends A2AResponse { /** * Constructs response with full parameters. @@ -26,7 +30,7 @@ public final class GetAuthenticatedExtendedCardResponse extends JSONRPCResponse< * @param result the agent card result * @param error the error if any */ - public GetAuthenticatedExtendedCardResponse(String jsonrpc, Object id, AgentCard result, JSONRPCError error) { + public GetAuthenticatedExtendedCardResponse(String jsonrpc, Object id, AgentCard result, A2AError error) { super(jsonrpc, id, result, error, AgentCard.class); } @@ -36,7 +40,7 @@ public GetAuthenticatedExtendedCardResponse(String jsonrpc, Object id, AgentCard * @param id the request ID * @param error the error */ - public GetAuthenticatedExtendedCardResponse(Object id, JSONRPCError error) { + public GetAuthenticatedExtendedCardResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java similarity index 91% rename from spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java index 8023be203..e0f11be83 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; import java.util.UUID; +import io.a2a.spec.GetTaskPushNotificationConfigParams; +import io.a2a.spec.TaskPushNotificationConfig; + /** * JSON-RPC request to retrieve push notification configuration for a task. *

    @@ -17,9 +22,6 @@ */ public final class GetTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "GetTaskPushNotificationConfig"; - /** * Constructs request with all parameters. * @@ -28,7 +30,7 @@ public final class GetTaskPushNotificationConfigRequest extends NonStreamingJSON * @param params the request parameters */ public GetTaskPushNotificationConfigRequest(String jsonrpc, Object id, GetTaskPushNotificationConfigParams params) { - super(jsonrpc, METHOD, id, params); + super(jsonrpc, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); } /** diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java similarity index 82% rename from spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java index b26d8edf1..3aa71c8b6 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskPushNotificationConfigResponse.java @@ -1,4 +1,7 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.A2AError; +import io.a2a.spec.TaskPushNotificationConfig; /** * JSON-RPC response containing a task's push notification configuration. @@ -7,13 +10,13 @@ * showing the current push notification endpoint and authentication settings. *

    * If no configuration exists or an error occurs, the error field will contain a - * {@link JSONRPCError}. + * {@link A2AError}. * * @see GetTaskPushNotificationConfigRequest for the corresponding request * @see TaskPushNotificationConfig for the configuration structure * @see A2A Protocol Specification */ -public final class GetTaskPushNotificationConfigResponse extends JSONRPCResponse { +public final class GetTaskPushNotificationConfigResponse extends A2AResponse { /** * Constructs response with full parameters. @@ -23,7 +26,7 @@ public final class GetTaskPushNotificationConfigResponse extends JSONRPCResponse * @param result the push notification config result * @param error the error if any */ - public GetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPushNotificationConfig result, JSONRPCError error) { + public GetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPushNotificationConfig result, A2AError error) { super(jsonrpc, id, result, error, TaskPushNotificationConfig.class); } @@ -33,7 +36,7 @@ public GetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPush * @param id the request ID * @param error the error */ - public GetTaskPushNotificationConfigResponse(Object id, JSONRPCError error) { + public GetTaskPushNotificationConfigResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/GetTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java similarity index 93% rename from spec/src/main/java/io/a2a/spec/GetTaskRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java index 12d39ff63..a08abe1be 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/GetTaskRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; import java.util.UUID; +import io.a2a.spec.Task; +import io.a2a.spec.TaskQueryParams; + /** * JSON-RPC request to retrieve task information by ID. *

    @@ -18,9 +23,6 @@ */ public final class GetTaskRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "GetTask"; - /** * Constructs request with all parameters. * @@ -29,7 +31,7 @@ public final class GetTaskRequest extends NonStreamingJSONRPCRequest * If the task is not found or an error occurs, the error field will be populated with - * a {@link JSONRPCError} (typically {@link TaskNotFoundError}) instead of a result. + * a {@link A2AError} (typically {@link TaskNotFoundError}) instead of a result. * * @see GetTaskRequest for the corresponding request * @see Task for the task structure * @see TaskNotFoundError for the common error case * @see A2A Protocol Specification */ -public final class GetTaskResponse extends JSONRPCResponse { +public final class GetTaskResponse extends A2AResponse { /** * Constructs response with full parameters. @@ -24,7 +28,7 @@ public final class GetTaskResponse extends JSONRPCResponse { * @param result the task result * @param error the error if any */ - public GetTaskResponse(String jsonrpc, Object id, Task result, JSONRPCError error) { + public GetTaskResponse(String jsonrpc, Object id, Task result, A2AError error) { super(jsonrpc, id, result, error, Task.class); } @@ -34,7 +38,7 @@ public GetTaskResponse(String jsonrpc, Object id, Task result, JSONRPCError erro * @param id the request ID * @param error the error */ - public GetTaskResponse(Object id, JSONRPCError error) { + public GetTaskResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigRequest.java similarity index 90% rename from spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigRequest.java index 8f7f3c11f..ebd5c98e5 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigRequest.java @@ -1,7 +1,13 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + import java.util.UUID; +import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.TaskPushNotificationConfig; + +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; + /** * JSON-RPC request to list all push notification configurations for a task. *

    @@ -17,9 +23,6 @@ */ public final class ListTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "ListTaskPushNotificationConfig"; - /** * Constructs request with all parameters. * @@ -28,7 +31,7 @@ public final class ListTaskPushNotificationConfigRequest extends NonStreamingJSO * @param params the request parameters */ public ListTaskPushNotificationConfigRequest(String jsonrpc, Object id, ListTaskPushNotificationConfigParams params) { - super(jsonrpc, METHOD, id, params); + super(jsonrpc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); } /** diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java similarity index 78% rename from spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java index 098fabe1c..e5e24739f 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTaskPushNotificationConfigResponse.java @@ -1,4 +1,8 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.A2AError; +import io.a2a.spec.ListTaskPushNotificationConfigResult; +import io.a2a.spec.TaskPushNotificationConfig; /** * JSON-RPC response containing all push notification configurations for a task with pagination support. @@ -7,14 +11,14 @@ * {@link TaskPushNotificationConfig} entries configured for the requested task, * showing all active notification endpoints with optional pagination information. *

    - * If an error occurs, the error field will contain a {@link JSONRPCError}. + * If an error occurs, the error field will contain a {@link A2AError}. * * @see ListTaskPushNotificationConfigRequest for the corresponding request * @see ListTaskPushNotificationConfigResult for the result structure * @see TaskPushNotificationConfig for the configuration structure * @see A2A Protocol Specification */ -public final class ListTaskPushNotificationConfigResponse extends JSONRPCResponse { +public final class ListTaskPushNotificationConfigResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -24,7 +28,7 @@ public final class ListTaskPushNotificationConfigResponse extends JSONRPCRespons * @param result the result containing list of push notification configurations and pagination info * @param error the error (if any) */ - public ListTaskPushNotificationConfigResponse(String jsonrpc, Object id, ListTaskPushNotificationConfigResult result, JSONRPCError error) { + public ListTaskPushNotificationConfigResponse(String jsonrpc, Object id, ListTaskPushNotificationConfigResult result, A2AError error) { super(jsonrpc, id, result, error, ListTaskPushNotificationConfigResult.class); } @@ -34,7 +38,7 @@ public ListTaskPushNotificationConfigResponse(String jsonrpc, Object id, ListTas * @param id the request ID * @param error the error */ - public ListTaskPushNotificationConfigResponse(Object id, JSONRPCError error) { + public ListTaskPushNotificationConfigResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/ListTasksRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java similarity index 92% rename from spec/src/main/java/io/a2a/spec/ListTasksRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java index a84a9a361..aa8d656bc 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksRequest.java @@ -1,15 +1,16 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; import java.util.UUID; +import io.a2a.spec.ListTasksParams; + /** * A list tasks request. */ public final class ListTasksRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "ListTasks"; - /** * Constructs request with all parameters. * @@ -18,7 +19,7 @@ public final class ListTasksRequest extends NonStreamingJSONRPCRequest { +public final class ListTasksResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -13,7 +15,7 @@ public final class ListTasksResponse extends JSONRPCResponse { * @param result the result * @param error the error if any */ - public ListTasksResponse(String jsonrpc, Object id, ListTasksResult result, JSONRPCError error) { + public ListTasksResponse(String jsonrpc, Object id, ListTasksResult result, A2AError error) { super(jsonrpc, id, result, error, ListTasksResult.class); } @@ -33,7 +35,7 @@ public ListTasksResponse(Object id, ListTasksResult result) { * @param id the request ID * @param error the error */ - public ListTasksResponse(Object id, JSONRPCError error) { + public ListTasksResponse(Object id, A2AError error) { this(null, id, null, error); } } diff --git a/spec/src/main/java/io/a2a/spec/ListTasksResult.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java similarity index 98% rename from spec/src/main/java/io/a2a/spec/ListTasksResult.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java index 959c547a6..9cf2adc60 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksResult.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/ListTasksResult.java @@ -1,10 +1,11 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; +import java.util.List; + +import io.a2a.spec.Task; import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; -import java.util.List; - /** * Result of a list tasks request containing matching tasks and pagination information. * diff --git a/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java similarity index 90% rename from spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java index 7264d7cdd..695b9969f 100644 --- a/spec/src/main/java/io/a2a/spec/NonStreamingJSONRPCRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/NonStreamingJSONRPCRequest.java @@ -1,11 +1,11 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; /** * Represents a non-streaming JSON-RPC request. * * @param the type of the request parameters */ -public abstract sealed class NonStreamingJSONRPCRequest extends JSONRPCRequest permits GetTaskRequest, +public abstract sealed class NonStreamingJSONRPCRequest extends A2ARequest permits GetTaskRequest, CancelTaskRequest, SetTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, SendMessageRequest, DeleteTaskPushNotificationConfigRequest, ListTaskPushNotificationConfigRequest, GetAuthenticatedExtendedCardRequest, ListTasksRequest { diff --git a/spec/src/main/java/io/a2a/spec/SendMessageRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java similarity index 91% rename from spec/src/main/java/io/a2a/spec/SendMessageRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java index 23b44dbaa..999361635 100644 --- a/spec/src/main/java/io/a2a/spec/SendMessageRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; import java.util.UUID; +import io.a2a.spec.MessageSendParams; +import io.a2a.spec.Task; + /** * JSON-RPC request for the {@code SendMessage} method in the A2A Protocol. *

    @@ -20,7 +25,7 @@ * with the {@code SendStreamingMessage} method instead. *

    * This class includes a fluent {@link Builder} for convenient request construction. The method - * name is fixed as {@value #METHOD} and is set automatically by the constructor. + * name is fixed as "SendMessage" and is set automatically by the constructor. * * @see SendStreamingMessageRequest * @see MessageSendParams @@ -29,11 +34,6 @@ */ public final class SendMessageRequest extends NonStreamingJSONRPCRequest { - /** - * The JSON-RPC method name for sending a message: "SendMessage". - */ - public static final String METHOD = "SendMessage"; - /** * Constructs a SendMessageRequest with the specified JSON-RPC fields. *

    @@ -46,7 +46,7 @@ public final class SendMessageRequest extends NonStreamingJSONRPCRequest - * The method name is automatically set to {@value SendMessageRequest#METHOD} and cannot be changed. + * The method name is automatically set to "SendMessage" and cannot be changed. * If no ID is provided, a UUID will be auto-generated when {@link #build()} is called. *

    * Example usage: diff --git a/spec/src/main/java/io/a2a/spec/SendMessageResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java similarity index 75% rename from spec/src/main/java/io/a2a/spec/SendMessageResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java index da01aa827..4f576dd01 100644 --- a/spec/src/main/java/io/a2a/spec/SendMessageResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendMessageResponse.java @@ -1,9 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.A2AError; +import io.a2a.spec.EventKind; /** * The response after receiving a send message request. */ -public final class SendMessageResponse extends JSONRPCResponse { +public final class SendMessageResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -13,7 +16,7 @@ public final class SendMessageResponse extends JSONRPCResponse { * @param result the result * @param error the error if any */ - public SendMessageResponse(String jsonrpc, Object id, EventKind result, JSONRPCError error) { + public SendMessageResponse(String jsonrpc, Object id, EventKind result, A2AError error) { super(jsonrpc, id, result, error, EventKind.class); } @@ -33,7 +36,7 @@ public SendMessageResponse(Object id, EventKind result) { * @param id the request ID * @param error the error */ - public SendMessageResponse(Object id, JSONRPCError error) { + public SendMessageResponse(Object id, A2AError error) { this(null, id, null, error); } } diff --git a/spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java similarity index 93% rename from spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java index 9148133c3..704b70435 100644 --- a/spec/src/main/java/io/a2a/spec/SendStreamingMessageRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SendStreamingMessageRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import java.util.UUID; +import io.a2a.spec.MessageSendParams; +import io.a2a.spec.StreamingEventKind; + /** * JSON-RPC request to initiate a new task with streaming event delivery. *

    @@ -21,9 +26,6 @@ */ public final class SendStreamingMessageRequest extends StreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "SendStreamingMessage"; - /** * Constructs request with all parameters. * @@ -32,7 +34,7 @@ public final class SendStreamingMessageRequest extends StreamingJSONRPCRequest * If an error occurs during request processing, the error field will be populated with - * a {@link JSONRPCError} instead of streaming events. + * a {@link A2AError} instead of streaming events. * * @see SendStreamingMessageRequest for the corresponding request * @see StreamingEventKind for the types of events that can be streamed * @see A2A Protocol Specification */ -public final class SendStreamingMessageResponse extends JSONRPCResponse { +public final class SendStreamingMessageResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -27,7 +34,7 @@ public final class SendStreamingMessageResponse extends JSONRPCResponse @@ -18,9 +23,6 @@ */ public final class SetTaskPushNotificationConfigRequest extends NonStreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "SetTaskPushNotificationConfig"; - /** * Constructs request with all parameters. * @@ -29,7 +31,7 @@ public final class SetTaskPushNotificationConfigRequest extends NonStreamingJSON * @param params the request parameters */ public SetTaskPushNotificationConfigRequest(String jsonrpc, Object id, TaskPushNotificationConfig params) { - super(jsonrpc, METHOD, id, params); + super(jsonrpc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, id, params); } /** diff --git a/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigResponse.java similarity index 78% rename from spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigResponse.java index 752c0de03..0c39b9713 100644 --- a/spec/src/main/java/io/a2a/spec/SetTaskPushNotificationConfigResponse.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SetTaskPushNotificationConfigResponse.java @@ -1,4 +1,8 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.A2AError; +import io.a2a.spec.PushNotificationNotSupportedError; +import io.a2a.spec.TaskPushNotificationConfig; /** * JSON-RPC response confirming push notification configuration for a task. @@ -8,14 +12,14 @@ * as stored by the agent. *

    * If push notifications are not supported or an error occurs, the error field will contain - * a {@link JSONRPCError} (e.g., {@link PushNotificationNotSupportedError}). + * a {@link A2AError} (e.g., {@link PushNotificationNotSupportedError}). * * @see SetTaskPushNotificationConfigRequest for the corresponding request * @see TaskPushNotificationConfig for the configuration structure * @see PushNotificationNotSupportedError for the error when unsupported * @see A2A Protocol Specification */ -public final class SetTaskPushNotificationConfigResponse extends JSONRPCResponse { +public final class SetTaskPushNotificationConfigResponse extends A2AResponse { /** * Constructs response with all parameters. @@ -25,7 +29,7 @@ public final class SetTaskPushNotificationConfigResponse extends JSONRPCResponse * @param result the push notification configuration * @param error the error (if any) */ - public SetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPushNotificationConfig result, JSONRPCError error) { + public SetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPushNotificationConfig result, A2AError error) { super(jsonrpc, id, result, error, TaskPushNotificationConfig.class); } @@ -35,7 +39,7 @@ public SetTaskPushNotificationConfigResponse(String jsonrpc, Object id, TaskPush * @param id the request ID * @param error the error */ - public SetTaskPushNotificationConfigResponse(Object id, JSONRPCError error) { + public SetTaskPushNotificationConfigResponse(Object id, A2AError error) { this(null, id, null, error); } diff --git a/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java similarity index 87% rename from spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java index 30033fc46..cbf33a72d 100644 --- a/spec/src/main/java/io/a2a/spec/StreamingJSONRPCRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/StreamingJSONRPCRequest.java @@ -1,9 +1,11 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import io.a2a.spec.StreamingEventKind; /** * Base class for JSON-RPC requests that support streaming responses in the A2A Protocol. *

    - * This sealed class extends {@link JSONRPCRequest} to provide specialized support for + * This sealed class extends {@link A2ARequest} to provide specialized support for * A2A Protocol methods that return streaming responses. Streaming requests enable * server-sent events and real-time updates to be pushed to clients as they occur, * rather than waiting for a complete response. @@ -27,7 +29,7 @@ * @see StreamingEventKind * @see A2A Protocol Specification */ -public abstract sealed class StreamingJSONRPCRequest extends JSONRPCRequest permits SubscribeToTaskRequest, +public abstract sealed class StreamingJSONRPCRequest extends A2ARequest permits SubscribeToTaskRequest, SendStreamingMessageRequest { StreamingJSONRPCRequest(String jsonrpc, String method, Object id, T params) { diff --git a/spec/src/main/java/io/a2a/spec/SubscribeToTaskRequest.java b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java similarity index 92% rename from spec/src/main/java/io/a2a/spec/SubscribeToTaskRequest.java rename to jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java index ba34bd4fd..27acb3a14 100644 --- a/spec/src/main/java/io/a2a/spec/SubscribeToTaskRequest.java +++ b/jsonrpc-common/src/main/java/io/a2a/jsonrpc/common/wrappers/SubscribeToTaskRequest.java @@ -1,7 +1,12 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.wrappers; + +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; import java.util.UUID; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.TaskIdParams; + /** * JSON-RPC request to resubscribe to an ongoing or completed task's event stream. *

    @@ -24,9 +29,6 @@ */ public final class SubscribeToTaskRequest extends StreamingJSONRPCRequest { - /** The JSON-RPC method name. */ - public static final String METHOD = "SubscribeToTask"; - /** * Constructs request with all parameters. * @@ -35,7 +37,7 @@ public final class SubscribeToTaskRequest extends StreamingJSONRPCRequest + * This package contains internal implementation classes that wrap A2A Protocol domain objects + * in JSON-RPC 2.0 message structures. These classes are used by JSON-RPC transport implementations + * and are not part of the public SDK API. + *

    + * Internal Use Only: Classes in this package are implementation details. + * The public API is in {@code io.a2a.spec}. + * + * @see io.a2a.spec + * @see JSON-RPC 2.0 Specification + */ +package io.a2a.jsonrpc.common.wrappers; diff --git a/spec/src/test/java/io/a2a/spec/JSONRPCErrorSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java similarity index 72% rename from spec/src/test/java/io/a2a/spec/JSONRPCErrorSerializationTest.java rename to jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java index 684f8a256..ff7ee5cc1 100644 --- a/spec/src/test/java/io/a2a/spec/JSONRPCErrorSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/A2AErrorSerializationTest.java @@ -1,11 +1,5 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.json; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; @@ -17,19 +11,34 @@ import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import java.util.List; + +import io.a2a.spec.A2AError; +import io.a2a.spec.ContentTypeNotSupportedError; +import io.a2a.spec.InternalError; +import io.a2a.spec.InvalidAgentResponseError; +import io.a2a.spec.InvalidParamsError; +import io.a2a.spec.InvalidRequestError; +import io.a2a.spec.JSONParseError; +import io.a2a.spec.MethodNotFoundError; +import io.a2a.spec.PushNotificationNotSupportedError; +import io.a2a.spec.TaskNotCancelableError; +import io.a2a.spec.TaskNotFoundError; +import io.a2a.spec.UnsupportedOperationError; +import org.junit.jupiter.api.Test; -public class JSONRPCErrorSerializationTest { +public class A2AErrorSerializationTest { @Test - public void shouldDeserializeToCorrectJSONRPCErrorSubclass() throws JsonProcessingException { + public void shouldDeserializeToCorrectA2AErrorSubclass() throws JsonProcessingException { String jsonTemplate = """ {"code": %s, "message": "error", "data": "anything"} """; - record ErrorCase(int code, Class clazz) {} + record ErrorCase(int code, Class clazz) {} List cases = List.of(new ErrorCase(JSON_PARSE_ERROR_CODE, JSONParseError.class), new ErrorCase(INVALID_REQUEST_ERROR_CODE, InvalidRequestError.class), @@ -42,12 +51,12 @@ record ErrorCase(int code, Class clazz) {} new ErrorCase(INVALID_AGENT_RESPONSE_ERROR_CODE, InvalidAgentResponseError.class), new ErrorCase(TASK_NOT_CANCELABLE_ERROR_CODE, TaskNotCancelableError.class), new ErrorCase(TASK_NOT_FOUND_ERROR_CODE, TaskNotFoundError.class), - new ErrorCase(Integer.MAX_VALUE, JSONRPCError.class) // Any unknown code will be treated as JSONRPCError + new ErrorCase(Integer.MAX_VALUE, A2AError.class) // Any unknown code will be treated as A2AError ); for (ErrorCase errorCase : cases) { String json = jsonTemplate.formatted(errorCase.code()); - JSONRPCError error = JsonUtil.fromJson(json, JSONRPCError.class); + A2AError error = JsonUtil.fromJson(json, A2AError.class); assertInstanceOf(errorCase.clazz(), error); assertEquals("error", error.getMessage()); assertEquals("anything", error.getData().toString()); diff --git a/spec/src/test/java/io/a2a/spec/StreamingEventKindSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java similarity index 96% rename from spec/src/test/java/io/a2a/spec/StreamingEventKindSerializationTest.java rename to jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java index 7c15447e1..08eea2835 100644 --- a/spec/src/test/java/io/a2a/spec/StreamingEventKindSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/StreamingEventKindSerializationTest.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.json; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -8,8 +8,15 @@ import java.util.List; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.spec.Artifact; +import io.a2a.spec.Message; +import io.a2a.spec.StreamingEventKind; +import io.a2a.spec.Task; +import io.a2a.spec.TaskArtifactUpdateEvent; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatus; +import io.a2a.spec.TaskStatusUpdateEvent; +import io.a2a.spec.TextPart; import org.junit.jupiter.api.Test; /** diff --git a/spec/src/test/java/io/a2a/spec/TaskSerializationTest.java b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java similarity index 98% rename from spec/src/test/java/io/a2a/spec/TaskSerializationTest.java rename to jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java index cded0e204..940fe4531 100644 --- a/spec/src/test/java/io/a2a/spec/TaskSerializationTest.java +++ b/jsonrpc-common/src/test/java/io/a2a/jsonrpc/common/json/TaskSerializationTest.java @@ -1,4 +1,4 @@ -package io.a2a.spec; +package io.a2a.jsonrpc.common.json; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,8 +10,17 @@ import java.util.List; import java.util.Map; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.spec.Artifact; +import io.a2a.spec.DataPart; +import io.a2a.spec.FilePart; +import io.a2a.spec.FileWithBytes; +import io.a2a.spec.FileWithUri; +import io.a2a.spec.Message; +import io.a2a.spec.Part; +import io.a2a.spec.Task; +import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatus; +import io.a2a.spec.TextPart; import org.junit.jupiter.api.Test; /** diff --git a/pom.xml b/pom.xml index 689e4f4ea..21ee72eb3 100644 --- a/pom.xml +++ b/pom.xml @@ -116,6 +116,11 @@ a2a-java-sdk-http-client ${project.version} + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-spec @@ -484,6 +489,7 @@ extras/push-notification-config-store-database-jpa extras/queue-manager-replicated http-client + jsonrpc-common integrations/microprofile-config reference/common reference/grpc diff --git a/reference/grpc/pom.xml b/reference/grpc/pom.xml index 0db7b0ca7..cbecf7470 100644 --- a/reference/grpc/pom.xml +++ b/reference/grpc/pom.xml @@ -31,6 +31,11 @@ ${project.groupId} a2a-java-sdk-server-common + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-tests-server-common diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java index 9f0559cdb..a2c2b13c8 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java +++ b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/A2AExtensionsInterceptor.java @@ -1,14 +1,15 @@ package io.a2a.server.grpc.quarkus; import jakarta.enterprise.context.ApplicationScoped; + +import io.a2a.common.A2AHeaders; +import io.a2a.transport.grpc.context.GrpcContextKeys; import io.grpc.Context; import io.grpc.Contexts; import io.grpc.Metadata; import io.grpc.ServerCall; import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; -import io.a2a.common.A2AHeaders; -import io.a2a.transport.grpc.context.GrpcContextKeys; /** * gRPC server interceptor that captures request metadata and context information, diff --git a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java index 6e51eae85..edd346d50 100644 --- a/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java +++ b/reference/grpc/src/main/java/io/a2a/server/grpc/quarkus/QuarkusGrpcHandler.java @@ -1,10 +1,10 @@ package io.a2a.server.grpc.quarkus; +import java.util.concurrent.Executor; + import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; -import java.util.concurrent.Executor; - import io.a2a.server.PublicAgentCard; import io.a2a.server.requesthandlers.RequestHandler; import io.a2a.server.util.async.Internal; diff --git a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java b/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java index ef28ada75..4136eb70b 100644 --- a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java +++ b/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/A2ATestResource.java @@ -18,13 +18,13 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.apps.common.TestUtilsBean; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.transport.grpc.handler.GrpcHandler; -import io.a2a.json.JsonUtil; @Path("/test") @ApplicationScoped diff --git a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java b/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java index b66f15b56..24320b94d 100644 --- a/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java +++ b/reference/grpc/src/test/java/io/a2a/server/grpc/quarkus/QuarkusA2AGrpcTest.java @@ -10,7 +10,6 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.quarkus.test.junit.QuarkusTest; - import org.junit.jupiter.api.AfterAll; @QuarkusTest diff --git a/reference/jsonrpc/pom.xml b/reference/jsonrpc/pom.xml index 11fa35377..97983421e 100644 --- a/reference/jsonrpc/pom.xml +++ b/reference/jsonrpc/pom.xml @@ -30,6 +30,11 @@ ${project.groupId} a2a-java-sdk-server-common + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-tests-server-common diff --git a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java index 4e4c6a294..699b003e0 100644 --- a/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java +++ b/reference/jsonrpc/src/main/java/io/a2a/server/apps/quarkus/A2AServerRoutes.java @@ -6,7 +6,6 @@ import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; import static jakarta.ws.rs.core.MediaType.SERVER_SENT_EVENTS; -import com.google.gson.JsonSyntaxException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -20,47 +19,48 @@ import jakarta.inject.Inject; import jakarta.inject.Singleton; -import io.a2a.json.JsonProcessingException; +import com.google.gson.JsonSyntaxException; import io.a2a.common.A2AHeaders; import io.a2a.grpc.utils.JSONRPCUtils; -import io.a2a.json.JsonMappingException; +import io.a2a.jsonrpc.common.json.IdJsonMappingException; +import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; +import io.a2a.jsonrpc.common.json.JsonMappingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.MethodNotFoundJsonMappingException; +import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; +import io.a2a.jsonrpc.common.wrappers.A2ARequest; +import io.a2a.jsonrpc.common.wrappers.A2AResponse; +import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; +import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; +import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; +import io.a2a.jsonrpc.common.wrappers.NonStreamingJSONRPCRequest; +import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.auth.User; import io.a2a.server.extensions.A2AExtensions; import io.a2a.server.util.async.Internal; +import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.CancelTaskResponse; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigResponse; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; -import io.a2a.spec.GetAuthenticatedExtendedCardResponse; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.GetTaskResponse; -import io.a2a.spec.IdJsonMappingException; import io.a2a.spec.InternalError; -import io.a2a.spec.InvalidParamsJsonMappingException; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.JSONRPCErrorResponse; -import io.a2a.spec.JSONRPCRequest; -import io.a2a.spec.JSONRPCResponse; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTaskPushNotificationConfigResponse; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.ListTasksResponse; -import io.a2a.spec.MethodNotFoundJsonMappingException; -import io.a2a.spec.NonStreamingJSONRPCRequest; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendMessageResponse; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SendStreamingMessageResponse; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.UnsupportedOperationError; import io.a2a.transport.jsonrpc.handler.JSONRPCHandler; import io.quarkus.security.Authenticated; @@ -97,11 +97,11 @@ public class A2AServerRoutes { public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { boolean streaming = false; ServerCallContext context = createCallContext(rc); - JSONRPCResponse nonStreamingResponse = null; - Multi> streamingResponse = null; - JSONRPCErrorResponse error = null; + A2AResponse nonStreamingResponse = null; + Multi> streamingResponse = null; + A2AErrorResponse error = null; try { - JSONRPCRequest request = JSONRPCUtils.parseRequestBody(body); + A2ARequest request = JSONRPCUtils.parseRequestBody(body); context.getState().put(METHOD_NAME_KEY, request.getMethod()); if (request instanceof NonStreamingJSONRPCRequest nonStreamingRequest) { nonStreamingResponse = processNonStreamingRequest(nonStreamingRequest, context); @@ -109,23 +109,23 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { streaming = true; streamingResponse = processStreamingRequest(request, context); } - } catch (JSONRPCError e) { - error = new JSONRPCErrorResponse(e); + } catch (A2AError e) { + error = new A2AErrorResponse(e); } catch (InvalidParamsJsonMappingException e) { - error = new JSONRPCErrorResponse(e.getId(), new io.a2a.spec.InvalidParamsError(null, e.getMessage(), null)); + error = new A2AErrorResponse(e.getId(), new io.a2a.spec.InvalidParamsError(null, e.getMessage(), null)); } catch (MethodNotFoundJsonMappingException e) { - error = new JSONRPCErrorResponse(e.getId(), new io.a2a.spec.MethodNotFoundError(null, e.getMessage(), null)); + error = new A2AErrorResponse(e.getId(), new io.a2a.spec.MethodNotFoundError(null, e.getMessage(), null)); } catch (IdJsonMappingException e) { - error = new JSONRPCErrorResponse(e.getId(), new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); + error = new A2AErrorResponse(e.getId(), new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); } catch (JsonMappingException e) { // General JsonMappingException - treat as InvalidRequest - error = new JSONRPCErrorResponse(new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); + error = new A2AErrorResponse(new io.a2a.spec.InvalidRequestError(null, e.getMessage(), null)); } catch (JsonSyntaxException e) { - error = new JSONRPCErrorResponse(new JSONParseError(e.getMessage())); + error = new A2AErrorResponse(new JSONParseError(e.getMessage())); } catch (JsonProcessingException e) { - error = new JSONRPCErrorResponse(new JSONParseError(e.getMessage())); + error = new A2AErrorResponse(new JSONParseError(e.getMessage())); } catch (Throwable t) { - error = new JSONRPCErrorResponse(new InternalError(t.getMessage())); + error = new A2AErrorResponse(new InternalError(t.getMessage())); } finally { if (error != null) { rc.response() @@ -133,7 +133,7 @@ public void invokeJSONRPCHandler(@Body String body, RoutingContext rc) { .putHeader(CONTENT_TYPE, APPLICATION_JSON) .end(serializeResponse(error)); } else if (streaming) { - final Multi> finalStreamingResponse = streamingResponse; + final Multi> finalStreamingResponse = streamingResponse; executor.execute(() -> { MultiSseSupport.subscribeObject( finalStreamingResponse.map(i -> (Object) i), rc); @@ -160,7 +160,7 @@ public AgentCard getAgentCard() { return jsonRpcHandler.getAgentCard(); } - private JSONRPCResponse processNonStreamingRequest(NonStreamingJSONRPCRequest request, ServerCallContext context) { + private A2AResponse processNonStreamingRequest(NonStreamingJSONRPCRequest request, ServerCallContext context) { if (request instanceof GetTaskRequest req) { return jsonRpcHandler.onGetTask(req, context); } @@ -191,9 +191,9 @@ private JSONRPCResponse processNonStreamingRequest(NonStreamingJSONRPCRequest return generateErrorResponse(request, new UnsupportedOperationError()); } - private Multi> processStreamingRequest( - JSONRPCRequest request, ServerCallContext context) { - Flow.Publisher> publisher; + private Multi> processStreamingRequest( + A2ARequest request, ServerCallContext context) { + Flow.Publisher> publisher; if (request instanceof SendStreamingMessageRequest req) { publisher = jsonRpcHandler.onMessageSendStream(req, context); } else if (request instanceof SubscribeToTaskRequest req) { @@ -204,8 +204,8 @@ private Multi> processStreamingRequest( return Multi.createFrom().publisher(publisher); } - private JSONRPCResponse generateErrorResponse(JSONRPCRequest request, JSONRPCError error) { - return new JSONRPCErrorResponse(request.getId(), error); + private A2AResponse generateErrorResponse(A2ARequest request, A2AError error) { + return new A2AErrorResponse(request.getId(), error); } static void setStreamingMultiSseSupportSubscribedRunnable(Runnable runnable) { @@ -252,9 +252,9 @@ public String getUsername() { } } - private static String serializeResponse(JSONRPCResponse response) { + private static String serializeResponse(A2AResponse response) { // For error responses, use Jackson serialization (errors are standardized) - if (response instanceof JSONRPCErrorResponse error) { + if (response instanceof A2AErrorResponse error) { return JSONRPCUtils.toJsonRPCErrorResponse(error.getId(), error.getError()); } if (response.getError() != null) { @@ -265,7 +265,7 @@ private static String serializeResponse(JSONRPCResponse response) { return JSONRPCUtils.toJsonRPCResultResponse(response.getId(), protoMessage); } - private static com.google.protobuf.MessageOrBuilder convertToProto(JSONRPCResponse response) { + private static com.google.protobuf.MessageOrBuilder convertToProto(A2AResponse response) { if (response instanceof GetTaskResponse r) { return io.a2a.grpc.utils.ProtoUtils.ToProto.task(r.getResult()); } else if (response instanceof CancelTaskResponse r) { @@ -366,10 +366,10 @@ public Buffer apply(Object o) { ReactiveRoutes.ServerSentEvent ev = (ReactiveRoutes.ServerSentEvent) o; long id = ev.id() != -1 ? ev.id() : count.getAndIncrement(); String e = ev.event() == null ? "" : "event: " + ev.event() + "\n"; - String data = serializeResponse((JSONRPCResponse) ev.data()); + String data = serializeResponse((A2AResponse) ev.data()); return Buffer.buffer(e + "data: " + data + "\nid: " + id + "\n\n"); } - String data = serializeResponse((JSONRPCResponse) o); + String data = serializeResponse((A2AResponse) o); return Buffer.buffer("data: " + data + "\nid: " + count.getAndIncrement() + "\n\n"); } }), rc); diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java index 5c7582da5..17edf650f 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java +++ b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2AServerRoutesTest.java @@ -1,5 +1,8 @@ package io.a2a.server.apps.quarkus; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import static io.a2a.transport.jsonrpc.context.JSONRPCContextKeys.METHOD_NAME_KEY; import static java.util.Collections.singletonList; @@ -17,32 +20,32 @@ import jakarta.enterprise.inject.Instance; +import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; +import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.AuthenticationInfo; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.CancelTaskResponse; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigResponse; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; -import io.a2a.spec.GetAuthenticatedExtendedCardResponse; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.GetTaskResponse; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTaskPushNotificationConfigResponse; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendMessageResponse; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SendStreamingMessageResponse; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.Task; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskState; @@ -57,6 +60,14 @@ import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; + /** * Unit test for JSON-RPC A2AServerRoutes that verifies the method names are properly set * in the ServerCallContext for all request types. @@ -154,7 +165,7 @@ public void testSendMessage_MethodNameSetInContext() { verify(mockJsonRpcHandler).onMessageSend(any(SendMessageRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SendMessageRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -201,7 +212,7 @@ public void testSendStreamingMessage_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SendStreamingMessageRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SEND_STREAMING_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -238,7 +249,7 @@ public void testGetTask_MethodNameSetInContext() { verify(mockJsonRpcHandler).onGetTask(any(GetTaskRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(GetTaskRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -274,7 +285,7 @@ public void testCancelTask_MethodNameSetInContext() { verify(mockJsonRpcHandler).onCancelTask(any(CancelTaskRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(CancelTaskRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -306,7 +317,7 @@ public void testTaskResubscription_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SubscribeToTaskRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SUBSCRIBE_TO_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -357,7 +368,7 @@ public void testSetTaskPushNotificationConfig_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SetTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -397,7 +408,7 @@ public void testGetTaskPushNotificationConfig_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(GetTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -437,7 +448,7 @@ public void testListTaskPushNotificationConfig_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(ListTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -469,13 +480,13 @@ public void testDeleteTaskPushNotificationConfig_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(DeleteTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test public void testGetAuthenticatedExtendedCard_MethodNameSetInContext() { // Arrange - String jsonRpcRequest = "{\"jsonrpc\":\"2.0\",\"id\":\"5\",\"method\":\"" + GetAuthenticatedExtendedCardRequest.METHOD + String jsonRpcRequest = "{\"jsonrpc\":\"2.0\",\"id\":\"5\",\"method\":\"" + GET_EXTENDED_AGENT_CARD_METHOD + "\",\"id\":1}"; when(mockRequestBody.asString()).thenReturn(jsonRpcRequest); @@ -506,7 +517,7 @@ public void testGetAuthenticatedExtendedCard_MethodNameSetInContext() { any(GetAuthenticatedExtendedCardRequest.class), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(GetAuthenticatedExtendedCardRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(GET_EXTENDED_AGENT_CARD_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } /** diff --git a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java index d3bfca712..12eae5a4d 100644 --- a/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java +++ b/reference/jsonrpc/src/test/java/io/a2a/server/apps/quarkus/A2ATestRoutes.java @@ -10,12 +10,12 @@ import jakarta.inject.Inject; import jakarta.inject.Singleton; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.apps.common.TestUtilsBean; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.json.JsonUtil; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.Param; import io.quarkus.vertx.web.Route; diff --git a/reference/rest/pom.xml b/reference/rest/pom.xml index b1ef2b03c..ec7e0dc1b 100644 --- a/reference/rest/pom.xml +++ b/reference/rest/pom.xml @@ -30,6 +30,11 @@ ${project.groupId} a2a-java-sdk-server-common + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-client-transport-rest diff --git a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java index f3b5f076c..d17815b8b 100644 --- a/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java +++ b/reference/rest/src/main/java/io/a2a/server/rest/quarkus/A2AServerRoutes.java @@ -1,11 +1,17 @@ package io.a2a.server.rest.quarkus; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import static io.a2a.transport.rest.context.RestContextKeys.HEADERS_KEY; import static io.a2a.transport.rest.context.RestContextKeys.METHOD_NAME_KEY; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; import static jakarta.ws.rs.core.MediaType.SERVER_SENT_EVENTS; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicLong; @@ -20,14 +26,16 @@ import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.auth.User; +import io.a2a.server.extensions.A2AExtensions; import io.a2a.server.util.async.Internal; +import io.a2a.spec.A2AError; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.MethodNotFoundError; import io.a2a.transport.rest.handler.RestHandler; import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; import io.a2a.transport.rest.handler.RestHandler.HTTPRestStreamingResponse; +import io.a2a.util.Utils; import io.quarkus.security.Authenticated; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.ReactiveRoutes; @@ -39,25 +47,17 @@ import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.RoutingContext; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import io.a2a.server.extensions.A2AExtensions; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SubscribeToTaskRequest; -import io.a2a.util.Utils; import org.jspecify.annotations.Nullable; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; + @Singleton @Authenticated public class A2AServerRoutes { @@ -83,7 +83,7 @@ public class A2AServerRoutes { @Route(regex = "^\\/(?[^\\/]*\\/?)message:send$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) public void sendMessage(@Body String body, RoutingContext rc) { - ServerCallContext context = createCallContext(rc, SendMessageRequest.METHOD); + ServerCallContext context = createCallContext(rc, SEND_MESSAGE_METHOD); HTTPRestResponse response = null; try { response = jsonRestHandler.sendMessage(body, extractTenant(rc), context); @@ -96,7 +96,7 @@ public void sendMessage(@Body String body, RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)message:stream$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) public void sendMessageStreaming(@Body String body, RoutingContext rc) { - ServerCallContext context = createCallContext(rc, SendStreamingMessageRequest.METHOD); + ServerCallContext context = createCallContext(rc, SEND_STREAMING_MESSAGE_METHOD); HTTPRestStreamingResponse streamingResponse = null; HTTPRestResponse error = null; try { @@ -121,7 +121,7 @@ public void sendMessageStreaming(@Body String body, RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\??", order = 0, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void listTasks(RoutingContext rc) { - ServerCallContext context = createCallContext(rc, ListTasksRequest.METHOD); + ServerCallContext context = createCallContext(rc, LIST_TASK_METHOD); HTTPRestResponse response = null; try { // Extract query parameters @@ -168,7 +168,7 @@ public void listTasks(RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^:^/]+)$", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void getTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, GetTaskRequest.METHOD); + ServerCallContext context = createCallContext(rc, GET_TASK_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { @@ -192,7 +192,7 @@ public void getTask(RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):cancel$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void cancelTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, CancelTaskRequest.METHOD); + ServerCallContext context = createCallContext(rc, CANCEL_TASK_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { @@ -201,7 +201,7 @@ public void cancelTask(RoutingContext rc) { response = jsonRestHandler.cancelTask(taskId, extractTenant(rc), context); } } catch (Throwable t) { - if (t instanceof JSONRPCError error) { + if (t instanceof A2AError error) { response = jsonRestHandler.createErrorResponse(error); } else { response = jsonRestHandler.createErrorResponse(new InternalError(t.getMessage())); @@ -225,7 +225,7 @@ private void sendResponse(RoutingContext rc, @Nullable HTTPRestResponse response @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+):subscribe$", order = 1, methods = {Route.HttpMethod.POST}, type = Route.HandlerType.BLOCKING) public void subscribeToTask(RoutingContext rc) { String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, SubscribeToTaskRequest.METHOD); + ServerCallContext context = createCallContext(rc, SUBSCRIBE_TO_TASK_METHOD); HTTPRestStreamingResponse streamingResponse = null; HTTPRestResponse error = null; try { @@ -255,7 +255,7 @@ public void subscribeToTask(RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs$", order = 1, methods = {Route.HttpMethod.POST}, consumes = {APPLICATION_JSON}, type = Route.HandlerType.BLOCKING) public void setTaskPushNotificationConfiguration(@Body String body, RoutingContext rc) { String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, SetTaskPushNotificationConfigRequest.METHOD); + ServerCallContext context = createCallContext(rc, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { @@ -274,7 +274,7 @@ public void setTaskPushNotificationConfiguration(@Body String body, RoutingConte public void getTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("taskId"); String configId = rc.pathParam("configId"); - ServerCallContext context = createCallContext(rc, GetTaskPushNotificationConfigRequest.METHOD); + ServerCallContext context = createCallContext(rc, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { @@ -292,7 +292,7 @@ public void getTaskPushNotificationConfiguration(RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs\\/$", order = 1, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void getTaskPushNotificationConfigurationWithoutId(RoutingContext rc) { String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, GetTaskPushNotificationConfigRequest.METHOD); + ServerCallContext context = createCallContext(rc, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { @@ -311,7 +311,7 @@ public void getTaskPushNotificationConfigurationWithoutId(RoutingContext rc) { @Route(regex = "^\\/(?[^\\/]*\\/?)tasks\\/(?[^/]+)\\/pushNotificationConfigs", order = 3, methods = {Route.HttpMethod.GET}, type = Route.HandlerType.BLOCKING) public void listTaskPushNotificationConfigurations(RoutingContext rc) { String taskId = rc.pathParam("taskId"); - ServerCallContext context = createCallContext(rc, ListTaskPushNotificationConfigRequest.METHOD); + ServerCallContext context = createCallContext(rc, LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { @@ -340,7 +340,7 @@ public void listTaskPushNotificationConfigurations(RoutingContext rc) { public void deleteTaskPushNotificationConfiguration(RoutingContext rc) { String taskId = rc.pathParam("taskId"); String configId = rc.pathParam("configId"); - ServerCallContext context = createCallContext(rc, DeleteTaskPushNotificationConfigRequest.METHOD); + ServerCallContext context = createCallContext(rc, DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); HTTPRestResponse response = null; try { if (taskId == null || taskId.isEmpty()) { diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java index 6ff3792c2..0f07b421a 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java +++ b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2AServerRoutesTest.java @@ -1,5 +1,14 @@ package io.a2a.server.rest.quarkus; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; import static io.a2a.transport.rest.context.RestContextKeys.METHOD_NAME_KEY; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -16,15 +25,6 @@ import jakarta.enterprise.inject.Instance; import io.a2a.server.ServerCallContext; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.transport.rest.handler.RestHandler; import io.a2a.transport.rest.handler.RestHandler.HTTPRestResponse; import io.vertx.core.Future; @@ -105,7 +105,7 @@ public void testSendMessage_MethodNameSetInContext() { verify(mockRestHandler).sendMessage(eq("{}"), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SendMessageRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SEND_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -127,7 +127,7 @@ public void testSendMessageStreaming_MethodNameSetInContext() { verify(mockRestHandler).sendStreamingMessage(eq("{}"), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SendStreamingMessageRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SEND_STREAMING_MESSAGE_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -149,7 +149,7 @@ public void testGetTask_MethodNameSetInContext() { verify(mockRestHandler).getTask(eq("task123"), any(), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(GetTaskRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(GET_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -171,7 +171,7 @@ public void testCancelTask_MethodNameSetInContext() { verify(mockRestHandler).cancelTask(eq("task123"), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(CancelTaskRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(CANCEL_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -194,7 +194,7 @@ public void testResubscribeTask_MethodNameSetInContext() { verify(mockRestHandler).subscribeToTask(eq("task123"), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SubscribeToTaskRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SUBSCRIBE_TO_TASK_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -217,7 +217,7 @@ public void testSetTaskPushNotificationConfiguration_MethodNameSetInContext() { verify(mockRestHandler).setTaskPushNotificationConfiguration(eq("task123"), eq("{}"), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(SetTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -242,7 +242,7 @@ public void testGetTaskPushNotificationConfiguration_MethodNameSetInContext() { contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(GetTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -265,7 +265,7 @@ public void testListTaskPushNotificationConfigurations_MethodNameSetInContext() verify(mockRestHandler).listTaskPushNotificationConfigurations(eq("task123"), anyInt(), anyString(), anyString(), contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(ListTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } @Test @@ -290,7 +290,7 @@ public void testDeleteTaskPushNotificationConfiguration_MethodNameSetInContext() contextCaptor.capture()); ServerCallContext capturedContext = contextCaptor.getValue(); assertNotNull(capturedContext); - assertEquals(DeleteTaskPushNotificationConfigRequest.METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); + assertEquals(DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD, capturedContext.getState().get(METHOD_NAME_KEY)); } /** diff --git a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java index ba5bd1cfd..57d6965a4 100644 --- a/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java +++ b/reference/rest/src/test/java/io/a2a/server/rest/quarkus/A2ATestRoutes.java @@ -1,7 +1,5 @@ package io.a2a.server.rest.quarkus; -import io.a2a.server.rest.quarkus.A2AServerRoutes; - import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; @@ -12,12 +10,12 @@ import jakarta.inject.Inject; import jakarta.inject.Singleton; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.apps.common.TestUtilsBean; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatusUpdateEvent; -import io.a2a.json.JsonUtil; import io.quarkus.vertx.web.Body; import io.quarkus.vertx.web.Param; import io.quarkus.vertx.web.Route; diff --git a/server-common/pom.xml b/server-common/pom.xml index 61aca7c9d..74cb6c7a1 100644 --- a/server-common/pom.xml +++ b/server-common/pom.xml @@ -21,6 +21,11 @@ ${project.groupId} a2a-java-sdk-spec + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-spec-grpc diff --git a/server-common/src/main/java/io/a2a/server/JSONRPCException.java b/server-common/src/main/java/io/a2a/server/JSONRPCException.java index cf7416b91..3911355d6 100644 --- a/server-common/src/main/java/io/a2a/server/JSONRPCException.java +++ b/server-common/src/main/java/io/a2a/server/JSONRPCException.java @@ -1,23 +1,23 @@ package io.a2a.server; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; /** * Exception wrapper for JSON-RPC protocol errors. *

    - * This exception encapsulates a {@link JSONRPCError} for handling + * This exception encapsulates a {@link A2AError} for handling * protocol-level errors during JSON-RPC request processing. *

    */ public class JSONRPCException extends Exception{ - private final JSONRPCError error; + private final A2AError error; /** * Creates a JSONRPCException wrapping the specified error. * * @param error the JSON-RPC error */ - public JSONRPCException(JSONRPCError error) { + public JSONRPCException(A2AError error) { this.error = error; } @@ -26,7 +26,7 @@ public JSONRPCException(JSONRPCError error) { * * @return the JSON-RPC error */ - public JSONRPCError getError() { + public A2AError getError() { return error; } } diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java b/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java index f753fed54..caa0c5cbf 100644 --- a/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java +++ b/server-common/src/main/java/io/a2a/server/agentexecution/AgentExecutor.java @@ -1,10 +1,10 @@ package io.a2a.server.agentexecution; import io.a2a.server.events.EventQueue; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; public interface AgentExecutor { - void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError; + void execute(RequestContext context, EventQueue eventQueue) throws A2AError; - void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError; + void cancel(RequestContext context, EventQueue eventQueue) throws A2AError; } diff --git a/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java b/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java index 0aa775649..0613d334c 100644 --- a/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java +++ b/server-common/src/main/java/io/a2a/server/agentexecution/RequestContext.java @@ -6,8 +6,6 @@ import java.util.UUID; import java.util.stream.Collectors; -import org.jspecify.annotations.Nullable; - import io.a2a.server.ServerCallContext; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.Message; @@ -16,6 +14,7 @@ import io.a2a.spec.Part; import io.a2a.spec.Task; import io.a2a.spec.TextPart; +import org.jspecify.annotations.Nullable; public class RequestContext { diff --git a/server-common/src/main/java/io/a2a/server/events/EventConsumer.java b/server-common/src/main/java/io/a2a/server/events/EventConsumer.java index d4fd7b682..7f1cbd4cc 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventConsumer.java +++ b/server-common/src/main/java/io/a2a/server/events/EventConsumer.java @@ -2,8 +2,6 @@ import java.util.concurrent.Flow; -import org.jspecify.annotations.Nullable; - import io.a2a.spec.A2AServerException; import io.a2a.spec.Event; import io.a2a.spec.Message; @@ -12,6 +10,7 @@ import mutiny.zero.BackpressureStrategy; import mutiny.zero.TubeConfiguration; import mutiny.zero.ZeroPublisher; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/events/EventQueue.java b/server-common/src/main/java/io/a2a/server/events/EventQueue.java index 7ce8ad3aa..a08f63084 100644 --- a/server-common/src/main/java/io/a2a/server/events/EventQueue.java +++ b/server-common/src/main/java/io/a2a/server/events/EventQueue.java @@ -9,10 +9,9 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import org.jspecify.annotations.Nullable; - import io.a2a.server.tasks.TaskStateProvider; import io.a2a.spec.Event; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java b/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java index 2ab9070d3..19179f50d 100644 --- a/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java +++ b/server-common/src/main/java/io/a2a/server/events/InMemoryQueueManager.java @@ -6,9 +6,8 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.jspecify.annotations.Nullable; - import io.a2a.server.tasks.TaskStateProvider; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java b/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java index 39f65a994..a83128a1a 100644 --- a/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java +++ b/server-common/src/main/java/io/a2a/server/extensions/A2AExtensions.java @@ -4,10 +4,9 @@ import java.util.List; import java.util.Set; -import org.jspecify.annotations.Nullable; - import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; +import org.jspecify.annotations.Nullable; public class A2AExtensions { diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java b/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java index 39fb01104..f3cb6f02e 100644 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java +++ b/server-common/src/main/java/io/a2a/server/requesthandlers/DefaultRequestHandler.java @@ -3,7 +3,7 @@ import static io.a2a.server.util.async.AsyncUtils.convertingProcessor; import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; import static io.a2a.server.util.async.AsyncUtils.processor; -import static java.util.concurrent.TimeUnit.*; +import static java.util.concurrent.TimeUnit.SECONDS; import java.time.Instant; import java.util.HashMap; @@ -21,16 +21,16 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; +import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import org.jspecify.annotations.Nullable; -import org.jspecify.annotations.NonNull; - +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.ServerCallContext; import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.agentexecution.SimpleRequestContextBuilder; +import io.a2a.server.config.A2AConfigProvider; import io.a2a.server.events.EnhancedRunnable; import io.a2a.server.events.EventConsumer; import io.a2a.server.events.EventQueue; @@ -43,17 +43,16 @@ import io.a2a.server.tasks.TaskManager; import io.a2a.server.tasks.TaskStore; import io.a2a.server.util.async.Internal; +import io.a2a.spec.A2AError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.Event; import io.a2a.spec.EventKind; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; import io.a2a.spec.PushNotificationConfig; @@ -66,8 +65,8 @@ import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.server.config.A2AConfigProvider; -import jakarta.annotation.PostConstruct; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -155,7 +154,7 @@ public static DefaultRequestHandler create(AgentExecutor agentExecutor, TaskStor } @Override - public Task onGetTask(TaskQueryParams params, ServerCallContext context) throws JSONRPCError { + public Task onGetTask(TaskQueryParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onGetTask {}", params.id()); Task task = taskStore.get(params.id()); if (task == null) { @@ -188,7 +187,7 @@ private static Task limitTaskHistory(Task task, @Nullable Integer historyLength) } @Override - public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext context) throws JSONRPCError { + public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onListTasks with contextId={}, status={}, pageSize={}, pageToken={}, lastUpdatedAfter={}", params.contextId(), params.status(), params.pageSize(), params.pageToken(), params.lastUpdatedAfter()); @@ -210,7 +209,7 @@ public ListTasksResult onListTasks(ListTasksParams params, ServerCallContext con } @Override - public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws JSONRPCError { + public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws A2AError { Task task = taskStore.get(params.id()); if (task == null) { throw new TaskNotFoundError(); @@ -262,7 +261,7 @@ public Task onCancelTask(TaskIdParams params, ServerCallContext context) throws } @Override - public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws JSONRPCError { + public EventKind onMessageSend(MessageSendParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onMessageSend - task: {}; context {}", params.message().taskId(), params.message().contextId()); MessageSendSetup mss = initMessageSend(params, context); @@ -398,7 +397,7 @@ public EventKind onMessageSend(MessageSendParams params, ServerCallContext conte @Override public Flow.Publisher onMessageSendStream( - MessageSendParams params, ServerCallContext context) throws JSONRPCError { + MessageSendParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onMessageSendStream START - task: {}; context: {}; runningAgents: {}; backgroundTasks: {}", params.message().taskId(), params.message().contextId(), runningAgents.size(), backgroundTasks.size()); MessageSendSetup mss = initMessageSend(params, context); @@ -560,7 +559,7 @@ private void startBackgroundConsumption() { @Override public TaskPushNotificationConfig onSetTaskPushNotificationConfig( - TaskPushNotificationConfig params, ServerCallContext context) throws JSONRPCError { + TaskPushNotificationConfig params, ServerCallContext context) throws A2AError { if (pushConfigStore == null) { throw new UnsupportedOperationError(); } @@ -575,7 +574,7 @@ public TaskPushNotificationConfig onSetTaskPushNotificationConfig( @Override public TaskPushNotificationConfig onGetTaskPushNotificationConfig( - GetTaskPushNotificationConfigParams params, ServerCallContext context) throws JSONRPCError { + GetTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { if (pushConfigStore == null) { throw new UnsupportedOperationError(); } @@ -607,7 +606,7 @@ private PushNotificationConfig getPushNotificationConfig(ListTaskPushNotificatio @Override public Flow.Publisher onResubscribeToTask( - TaskIdParams params, ServerCallContext context) throws JSONRPCError { + TaskIdParams params, ServerCallContext context) throws A2AError { LOGGER.debug("onResubscribeToTask - taskId: {}", params.id()); Task task = taskStore.get(params.id()); if (task == null) { @@ -638,7 +637,7 @@ public Flow.Publisher onResubscribeToTask( @Override public ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig( - ListTaskPushNotificationConfigParams params, ServerCallContext context) throws JSONRPCError { + ListTaskPushNotificationConfigParams params, ServerCallContext context) throws A2AError { if (pushConfigStore == null) { throw new UnsupportedOperationError(); } diff --git a/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java b/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java index ff7384e75..6d99fe399 100644 --- a/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java +++ b/server-common/src/main/java/io/a2a/server/requesthandlers/RequestHandler.java @@ -1,17 +1,16 @@ package io.a2a.server.requesthandlers; -import java.util.List; import java.util.concurrent.Flow; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.ServerCallContext; +import io.a2a.spec.A2AError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.MessageSendParams; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; @@ -22,41 +21,41 @@ public interface RequestHandler { Task onGetTask( TaskQueryParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; ListTasksResult onListTasks( ListTasksParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; Task onCancelTask( TaskIdParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; EventKind onMessageSend( MessageSendParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; Flow.Publisher onMessageSendStream( MessageSendParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; TaskPushNotificationConfig onSetTaskPushNotificationConfig( TaskPushNotificationConfig params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; TaskPushNotificationConfig onGetTaskPushNotificationConfig( GetTaskPushNotificationConfigParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; Flow.Publisher onResubscribeToTask( TaskIdParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; ListTaskPushNotificationConfigResult onListTaskPushNotificationConfig( ListTaskPushNotificationConfigParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; void onDeleteTaskPushNotificationConfig( DeleteTaskPushNotificationConfigParams params, - ServerCallContext context) throws JSONRPCError; + ServerCallContext context) throws A2AError; } diff --git a/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java b/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java index c6c887577..35a248373 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java +++ b/server-common/src/main/java/io/a2a/server/tasks/BasePushNotificationSender.java @@ -4,23 +4,21 @@ import static io.a2a.client.http.A2AHttpClient.CONTENT_TYPE; import static io.a2a.common.A2AHeaders.X_A2A_NOTIFICATION_TOKEN; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - import java.io.IOException; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.JdkA2AHttpClient; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java b/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java index 8dfeeebdb..093ff910d 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java +++ b/server-common/src/main/java/io/a2a/server/tasks/InMemoryPushNotificationConfigStore.java @@ -1,10 +1,5 @@ package io.a2a.server.tasks; -import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigResult; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -12,6 +7,11 @@ import java.util.List; import java.util.Map; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import io.a2a.spec.ListTaskPushNotificationConfigParams; +import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.TaskPushNotificationConfig; diff --git a/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java b/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java index 669fee0a8..d2d9362ca 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java +++ b/server-common/src/main/java/io/a2a/server/tasks/InMemoryTaskStore.java @@ -7,9 +7,9 @@ import jakarta.enterprise.context.ApplicationScoped; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.Artifact; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.Task; import org.jspecify.annotations.Nullable; diff --git a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java index 16a658f0e..222b06055 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java +++ b/server-common/src/main/java/io/a2a/server/tasks/PushNotificationConfigStore.java @@ -2,8 +2,6 @@ import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; - - import io.a2a.spec.PushNotificationConfig; /** diff --git a/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java b/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java index 0fd62113f..95684e199 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java +++ b/server-common/src/main/java/io/a2a/server/tasks/ResultAggregator.java @@ -11,19 +11,18 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import org.jspecify.annotations.Nullable; - import io.a2a.server.events.EventConsumer; import io.a2a.server.events.EventQueueItem; +import io.a2a.spec.A2AError; import io.a2a.spec.A2AServerException; import io.a2a.spec.Event; import io.a2a.spec.EventKind; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.util.Utils; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,7 +65,7 @@ public Flow.Publisher consumeAndEmit(EventConsumer consumer) { }); } - public EventKind consumeAll(EventConsumer consumer) throws JSONRPCError { + public EventKind consumeAll(EventConsumer consumer) throws A2AError { AtomicReference returnedEvent = new AtomicReference<>(); Flow.Publisher allItems = consumer.consumeAll(); AtomicReference error = new AtomicReference<>(); @@ -111,7 +110,7 @@ public EventKind consumeAll(EventConsumer consumer) throws JSONRPCError { return task; } - public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean blocking) throws JSONRPCError { + public EventTypeAndInterrupt consumeAndBreakOnInterrupt(EventConsumer consumer, boolean blocking) throws A2AError { Flow.Publisher allItems = consumer.consumeAll(); AtomicReference message = new AtomicReference<>(); AtomicBoolean interrupted = new AtomicBoolean(false); diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java b/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java index 55b24e409..fd3696a60 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java +++ b/server-common/src/main/java/io/a2a/server/tasks/TaskManager.java @@ -5,12 +5,11 @@ import static io.a2a.util.Utils.appendArtifactToTask; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.jspecify.annotations.Nullable; - import io.a2a.spec.A2AServerException; import io.a2a.spec.Event; import io.a2a.spec.InvalidParamsError; @@ -19,7 +18,7 @@ import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; -import java.util.Collections; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java b/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java index 7d15e032a..00f9e56a2 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java +++ b/server-common/src/main/java/io/a2a/server/tasks/TaskStore.java @@ -1,10 +1,9 @@ package io.a2a.server.tasks; -import org.jspecify.annotations.Nullable; - +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Task; +import org.jspecify.annotations.Nullable; /** * Storage interface for managing task persistence. diff --git a/server-common/src/main/java/io/a2a/server/tasks/TaskUpdater.java b/server-common/src/main/java/io/a2a/server/tasks/TaskUpdater.java index c4044603d..022cde56b 100644 --- a/server-common/src/main/java/io/a2a/server/tasks/TaskUpdater.java +++ b/server-common/src/main/java/io/a2a/server/tasks/TaskUpdater.java @@ -5,8 +5,6 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; -import org.jspecify.annotations.Nullable; - import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.spec.Artifact; @@ -16,6 +14,7 @@ import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; +import org.jspecify.annotations.Nullable; public class TaskUpdater { private final EventQueue eventQueue; diff --git a/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java b/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java index ada7a53fa..633b38ced 100644 --- a/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java +++ b/server-common/src/main/java/io/a2a/server/util/ArtifactUtils.java @@ -4,12 +4,11 @@ import java.util.Map; import java.util.UUID; -import org.jspecify.annotations.Nullable; - import io.a2a.spec.Artifact; import io.a2a.spec.DataPart; import io.a2a.spec.Part; import io.a2a.spec.TextPart; +import org.jspecify.annotations.Nullable; /** * Utility functions for creating A2A Artifact objects. diff --git a/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java b/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java index e4b135999..e26dd55fb 100644 --- a/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java +++ b/server-common/src/main/java/io/a2a/server/util/async/AsyncExecutorProducer.java @@ -14,9 +14,8 @@ import jakarta.enterprise.inject.Produces; import jakarta.inject.Inject; -import org.jspecify.annotations.Nullable; - import io.a2a.server.config.A2AConfigProvider; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java b/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java index 8d39d2e8a..4d1d4f9c4 100644 --- a/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java +++ b/server-common/src/main/java/io/a2a/server/util/async/AsyncUtils.java @@ -7,14 +7,13 @@ import java.util.function.Consumer; import java.util.function.Function; -import org.jspecify.annotations.Nullable; - import io.a2a.util.Assert; import mutiny.zero.BackpressureStrategy; import mutiny.zero.Tube; import mutiny.zero.TubeConfiguration; import mutiny.zero.ZeroPublisher; import mutiny.zero.operators.Transform; +import org.jspecify.annotations.Nullable; public class AsyncUtils { diff --git a/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java b/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java index 3ba6c4522..1c913ab7f 100644 --- a/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java +++ b/server-common/src/test/java/io/a2a/server/AgentCardValidatorTest.java @@ -1,10 +1,9 @@ package io.a2a.server; -import io.a2a.spec.AgentCapabilities; -import io.a2a.spec.AgentCard; -import io.a2a.spec.AgentInterface; -import io.a2a.spec.TransportProtocol; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collections; import java.util.List; @@ -13,10 +12,11 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; +import io.a2a.spec.AgentCapabilities; +import io.a2a.spec.AgentCard; +import io.a2a.spec.AgentInterface; +import io.a2a.spec.TransportProtocol; +import org.junit.jupiter.api.Test; public class AgentCardValidatorTest { diff --git a/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java b/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java index c12a48e27..911b81540 100644 --- a/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java +++ b/server-common/src/test/java/io/a2a/server/ServerCallContextTest.java @@ -9,9 +9,8 @@ import java.util.Map; import java.util.Set; -import org.junit.jupiter.api.Test; - import io.a2a.server.auth.User; +import org.junit.jupiter.api.Test; class ServerCallContextTest { diff --git a/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java b/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java index d75829f0b..433ebcac3 100644 --- a/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java +++ b/server-common/src/test/java/io/a2a/server/agentexecution/RequestContextTest.java @@ -9,20 +9,20 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + import io.a2a.spec.InvalidParamsError; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; import io.a2a.spec.Task; -import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskState; +import io.a2a.spec.TaskStatus; import io.a2a.spec.TextPart; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - public class RequestContextTest { @Test diff --git a/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java b/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java index f7f95f01e..6114e8f21 100644 --- a/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java +++ b/server-common/src/test/java/io/a2a/server/events/EventConsumerTest.java @@ -1,5 +1,6 @@ package io.a2a.server.events; +import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -14,12 +15,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import io.a2a.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; import io.a2a.spec.A2AError; import io.a2a.spec.A2AServerException; import io.a2a.spec.Artifact; import io.a2a.spec.Event; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -27,7 +27,6 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; -import io.a2a.util.Utils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -61,25 +60,25 @@ public void init() { @Test public void testConsumeOneTaskEvent() throws Exception { - Task event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Task event = fromJson(MINIMAL_TASK, Task.class); enqueueAndConsumeOneEvent(event); } @Test public void testConsumeOneMessageEvent() throws Exception { - Event event = Utils.unmarshalFrom(MESSAGE_PAYLOAD, Message.class); + Event event = fromJson(MESSAGE_PAYLOAD, Message.class); enqueueAndConsumeOneEvent(event); } @Test public void testConsumeOneA2AErrorEvent() throws Exception { - Event event = new A2AError() {}; + Event event = new A2AError(-1, "", null); enqueueAndConsumeOneEvent(event); } @Test public void testConsumeOneJsonRpcErrorEvent() throws Exception { - Event event = new JSONRPCError(123, "Some Error", null); + Event event = new A2AError(123, "Some Error", null); enqueueAndConsumeOneEvent(event); } @@ -91,7 +90,7 @@ public void testConsumeOneQueueEmpty() throws A2AServerException { @Test public void testConsumeAllMultipleEvents() throws JsonProcessingException { List events = List.of( - Utils.unmarshalFrom(MINIMAL_TASK, Task.class), + fromJson(MINIMAL_TASK, Task.class), TaskArtifactUpdateEvent.builder() .taskId("task-123") .contextId("session-xyz") @@ -152,7 +151,7 @@ public void onComplete() { @Test public void testConsumeUntilMessage() throws Exception { List events = List.of( - Utils.unmarshalFrom(MINIMAL_TASK, Task.class), + fromJson(MINIMAL_TASK, Task.class), TaskArtifactUpdateEvent.builder() .taskId("task-123") .contextId("session-xyz") @@ -212,7 +211,7 @@ public void onComplete() { @Test public void testConsumeMessageEvents() throws Exception { - Message message = Utils.unmarshalFrom(MESSAGE_PAYLOAD, Message.class); + Message message = fromJson(MESSAGE_PAYLOAD, Message.class); Message message2 = Message.builder(message).build(); List events = List.of(message, message2); @@ -391,7 +390,7 @@ public void testConsumeAllHandlesQueueClosedException() throws Exception { EventConsumer consumer = new EventConsumer(queue); // Add a message event (which will complete the stream) - Event message = Utils.unmarshalFrom(MESSAGE_PAYLOAD, Message.class); + Event message = fromJson(MESSAGE_PAYLOAD, Message.class); queue.enqueueEvent(message); // Close the queue before consuming diff --git a/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java b/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java index 6ac904b9e..a3dc7d916 100644 --- a/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java +++ b/server-common/src/test/java/io/a2a/server/events/EventQueueTest.java @@ -1,5 +1,6 @@ package io.a2a.server.events; +import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -11,9 +12,9 @@ import java.util.List; +import io.a2a.spec.A2AError; import io.a2a.spec.Artifact; import io.a2a.spec.Event; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -22,7 +23,6 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; -import io.a2a.util.Utils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -98,7 +98,7 @@ public void testEnqueueEventPropagagesToChildren() throws Exception { EventQueue parentQueue = EventQueue.builder().build(); EventQueue childQueue = parentQueue.tap(); - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); parentQueue.enqueueEvent(event); // Event should be available in both parent and child queues @@ -115,8 +115,8 @@ public void testMultipleChildQueuesReceiveEvents() throws Exception { EventQueue childQueue1 = parentQueue.tap(); EventQueue childQueue2 = parentQueue.tap(); - Event event1 = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); - Event event2 = Utils.unmarshalFrom(MESSAGE_PAYLOAD, Message.class); + Event event1 = fromJson(MINIMAL_TASK, Task.class); + Event event2 = fromJson(MESSAGE_PAYLOAD, Message.class); parentQueue.enqueueEvent(event1); parentQueue.enqueueEvent(event2); @@ -138,7 +138,7 @@ public void testChildQueueDequeueIndependently() throws Exception { EventQueue childQueue1 = parentQueue.tap(); EventQueue childQueue2 = parentQueue.tap(); - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); parentQueue.enqueueEvent(event); // Dequeue from child1 first @@ -161,7 +161,7 @@ public void testCloseImmediatePropagationToChildren() throws Exception { EventQueue childQueue = parentQueue.tap(); // Add events to both parent and child - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); parentQueue.enqueueEvent(event); assertFalse(childQueue.isClosed()); @@ -188,7 +188,7 @@ public void testCloseImmediatePropagationToChildren() throws Exception { @Test public void testEnqueueEventWhenClosed() throws Exception { EventQueue queue = EventQueue.builder().build(); - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); queue.close(); // Close the queue first assertTrue(queue.isClosed()); @@ -218,7 +218,7 @@ public void testDequeueEventWhenClosedAndEmpty() throws Exception { @Test public void testDequeueEventWhenClosedButHasEvents() throws Exception { EventQueue queue = EventQueue.builder().build(); - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); queue.enqueueEvent(event); queue.close(); // Graceful close - events should remain @@ -234,7 +234,7 @@ public void testDequeueEventWhenClosedButHasEvents() throws Exception { @Test public void testEnqueueAndDequeueEvent() throws Exception { - Event event = Utils.unmarshalFrom(MESSAGE_PAYLOAD, Message.class); + Event event = fromJson(MESSAGE_PAYLOAD, Message.class); eventQueue.enqueueEvent(event); Event dequeuedEvent = eventQueue.dequeueEventItem(200).getEvent(); assertSame(event, dequeuedEvent); @@ -242,7 +242,7 @@ public void testEnqueueAndDequeueEvent() throws Exception { @Test public void testDequeueEventNoWait() throws Exception { - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); eventQueue.enqueueEvent(event); Event dequeuedEvent = eventQueue.dequeueEventItem(-1).getEvent(); assertSame(event, dequeuedEvent); @@ -288,7 +288,7 @@ public void testTaskDone() throws Exception { public void testEnqueueDifferentEventTypes() throws Exception { List events = List.of( new TaskNotFoundError(), - new JSONRPCError(111, "rpc error", null)); + new A2AError(111, "rpc error", null)); for (Event event : events) { eventQueue.enqueueEvent(event); @@ -303,7 +303,7 @@ public void testEnqueueDifferentEventTypes() throws Exception { */ @Test public void testCloseGracefulSetsFlag() throws Exception { - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); eventQueue.enqueueEvent(event); eventQueue.close(false); // Graceful close @@ -316,7 +316,7 @@ public void testCloseGracefulSetsFlag() throws Exception { */ @Test public void testCloseImmediateClearsQueue() throws Exception { - Event event = Utils.unmarshalFrom(MINIMAL_TASK, Task.class); + Event event = fromJson(MINIMAL_TASK, Task.class); eventQueue.enqueueEvent(event); eventQueue.close(true); // Immediate close diff --git a/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java b/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java index 27d5ca08a..b9dec6364 100644 --- a/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java +++ b/server-common/src/test/java/io/a2a/server/extensions/A2AExtensionsTest.java @@ -9,12 +9,11 @@ import java.util.List; import java.util.Set; -import org.junit.jupiter.api.Test; - import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentExtension; import io.a2a.spec.AgentInterface; +import org.junit.jupiter.api.Test; class A2AExtensionsTest { diff --git a/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java b/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java index 0020fe947..8038bc147 100644 --- a/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java +++ b/server-common/src/test/java/io/a2a/server/requesthandlers/AbstractA2ARequestHandlerTest.java @@ -20,8 +20,8 @@ import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpResponse; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; @@ -33,11 +33,11 @@ import io.a2a.server.tasks.PushNotificationConfigStore; import io.a2a.server.tasks.PushNotificationSender; import io.a2a.server.tasks.TaskStore; +import io.a2a.spec.A2AError; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; import io.a2a.spec.Event; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.Message; import io.a2a.spec.Task; import io.a2a.spec.TaskState; @@ -80,14 +80,14 @@ public class AbstractA2ARequestHandlerTest { public void init() { executor = new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { if (agentExecutorExecute != null) { agentExecutorExecute.invoke(context, eventQueue); } } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { if (agentExecutorCancel != null) { agentExecutorCancel.invoke(context, eventQueue); } @@ -149,7 +149,7 @@ private static String loadPreferredTransportFromProperties() { } protected interface AgentExecutorMethod { - void invoke(RequestContext context, EventQueue eventQueue) throws JSONRPCError; + void invoke(RequestContext context, EventQueue eventQueue) throws A2AError; } /** diff --git a/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java b/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java index 31a57f137..293babe4e 100644 --- a/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java +++ b/server-common/src/test/java/io/a2a/server/requesthandlers/DefaultRequestHandlerTest.java @@ -21,7 +21,7 @@ import io.a2a.server.tasks.InMemoryPushNotificationConfigStore; import io.a2a.server.tasks.InMemoryTaskStore; import io.a2a.server.tasks.TaskUpdater; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.Message; @@ -959,7 +959,7 @@ private static class TestAgentExecutor implements AgentExecutor { private volatile boolean executing = false; interface ExecuteCallback { - void call(RequestContext context, EventQueue queue) throws JSONRPCError; + void call(RequestContext context, EventQueue queue) throws A2AError; } void setExecuteCallback(ExecuteCallback callback) { @@ -971,7 +971,7 @@ boolean isExecuting() { } @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { executing = true; try { if (executeCallback != null) { @@ -993,7 +993,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { // Simple cancel implementation executing = false; } diff --git a/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java b/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java index 05adb948c..e814c1c15 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/InMemoryTaskStoreTest.java @@ -1,10 +1,10 @@ package io.a2a.server.tasks; +import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import io.a2a.spec.Task; -import io.a2a.util.Utils; import org.junit.jupiter.api.Test; public class InMemoryTaskStoreTest { @@ -18,7 +18,7 @@ public class InMemoryTaskStoreTest { @Test public void testSaveAndGet() throws Exception { InMemoryTaskStore store = new InMemoryTaskStore(); - Task task = Utils.unmarshalFrom(TASK_JSON, Task.class); + Task task = fromJson(TASK_JSON, Task.class); store.save(task); Task retrieved = store.get(task.id()); assertSame(task, retrieved); @@ -34,7 +34,7 @@ public void testGetNonExistent() throws Exception { @Test public void testDelete() throws Exception { InMemoryTaskStore store = new InMemoryTaskStore(); - Task task = Utils.unmarshalFrom(TASK_JSON, Task.class); + Task task = fromJson(TASK_JSON, Task.class); store.save(task); store.delete(task.id()); Task retrieved = store.get(task.id()); diff --git a/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java b/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java index fcc9e9cf0..7bb67f681 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/PushNotificationSenderTest.java @@ -16,18 +16,17 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpResponse; import io.a2a.common.A2AHeaders; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.Task; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class PushNotificationSenderTest { diff --git a/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java b/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java index f39382878..f14ebc0fe 100644 --- a/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java +++ b/server-common/src/test/java/io/a2a/server/tasks/TaskManagerTest.java @@ -1,5 +1,6 @@ package io.a2a.server.tasks; +import static io.a2a.jsonrpc.common.json.JsonUtil.fromJson; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; @@ -22,7 +23,6 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; -import io.a2a.util.Utils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -40,7 +40,7 @@ public class TaskManagerTest { @BeforeEach public void init() throws Exception { - minimalTask = Utils.unmarshalFrom(TASK_JSON, Task.class); + minimalTask = fromJson(TASK_JSON, Task.class); taskStore = new InMemoryTaskStore(); taskManager = new TaskManager(minimalTask.id(), minimalTask.contextId(), taskStore, null); } diff --git a/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java b/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java index 8b4bd628c..34912efe6 100644 --- a/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java +++ b/server-common/src/test/java/io/a2a/server/util/ArtifactUtilsTest.java @@ -1,22 +1,21 @@ package io.a2a.server.util; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import java.util.List; import java.util.Map; import java.util.UUID; -import org.junit.jupiter.api.Test; - import io.a2a.spec.Artifact; import io.a2a.spec.DataPart; import io.a2a.spec.Part; import io.a2a.spec.TextPart; +import org.junit.jupiter.api.Test; class ArtifactUtilsTest { @Test diff --git a/spec-grpc/pom.xml b/spec-grpc/pom.xml index 94b3fb939..8938cdf1d 100644 --- a/spec-grpc/pom.xml +++ b/spec-grpc/pom.xml @@ -24,6 +24,10 @@ ${project.groupId} a2a-java-sdk-spec
    + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + com.google.protobuf protobuf-java @@ -92,7 +96,7 @@ io.github.ascopes protobuf-maven-plugin - 4.0.2 + 4.0.3 ${skip.protobuf.generate} true diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java index b47a56e37..4c1728753 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/A2ACommonFieldMapper.java @@ -3,6 +3,7 @@ import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -10,7 +11,6 @@ import com.google.protobuf.Struct; import com.google.protobuf.Timestamp; import com.google.protobuf.Value; -import java.util.Collections; import org.mapstruct.Mapper; import org.mapstruct.Named; diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DataPartMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DataPartMapper.java index 9ee0f94d3..68a79eea6 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/DataPartMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/DataPartMapper.java @@ -2,7 +2,6 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.ObjectFactory; /** * Mapper between {@link io.a2a.spec.DataPart} and {@link io.a2a.grpc.DataPart}. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/FilePartMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/FilePartMapper.java index 2174f2dc8..2b1993756 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/FilePartMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/FilePartMapper.java @@ -1,12 +1,13 @@ package io.a2a.grpc.mapper; +import java.util.Base64; + import com.google.protobuf.ByteString; import io.a2a.spec.FileContent; import io.a2a.spec.FileWithBytes; import io.a2a.spec.FileWithUri; import io.a2a.spec.InvalidRequestError; -import java.util.Base64; import org.mapstruct.Mapper; /** diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java index 6189daa4f..599877002 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/ListTasksResultMapper.java @@ -1,11 +1,11 @@ package io.a2a.grpc.mapper; -import io.a2a.spec.ListTasksResult; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import org.mapstruct.Mapper; import org.mapstruct.Mapping; /** - * Mapper between {@link io.a2a.spec.ListTasksResult} and {@link io.a2a.grpc.ListTasksResponse}. + * Mapper between {@link ListTasksResult} and {@link io.a2a.grpc.ListTasksResponse}. *

    * Handles conversion with null handling for nextPageToken field. * Uses ADDER_PREFERRED strategy to avoid ProtocolMessageList instantiation issues. diff --git a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java index 10faa303f..4768fd5c7 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/mapper/SubscribeToTaskRequestMapper.java @@ -1,10 +1,10 @@ package io.a2a.grpc.mapper; -import io.a2a.spec.SubscribeToTaskRequest; +import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import org.mapstruct.Mapper; /** - * Mapper between {@link io.a2a.spec.SubscribeToTaskRequest} and {@link io.a2a.grpc.SubscribeToTaskRequest}. + * Mapper between {@link SubscribeToTaskRequest} and {@link io.a2a.grpc.SubscribeToTaskRequest}. *

    * The mapping handles the structural difference between domain and proto representations: *

      diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java b/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java index 85d5b9f2e..37b1e9f34 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/utils/JSONRPCUtils.java @@ -1,6 +1,28 @@ package io.a2a.grpc.utils; -import io.a2a.json.JsonMappingException; +import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; +import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; +import static io.a2a.spec.A2AMethods.CANCEL_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_EXTENDED_AGENT_CARD_METHOD; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; @@ -11,65 +33,56 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import io.a2a.grpc.StreamResponse; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.CancelTaskResponse; +import io.a2a.jsonrpc.common.json.IdJsonMappingException; +import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; +import io.a2a.jsonrpc.common.json.JsonMappingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.MethodNotFoundJsonMappingException; +import io.a2a.jsonrpc.common.wrappers.A2AMessage; +import io.a2a.jsonrpc.common.wrappers.A2ARequest; +import io.a2a.jsonrpc.common.wrappers.A2AResponse; +import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; +import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; +import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; +import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; +import io.a2a.spec.A2AError; import io.a2a.spec.ContentTypeNotSupportedError; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigResponse; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; -import io.a2a.spec.GetAuthenticatedExtendedCardResponse; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.GetTaskResponse; -import io.a2a.spec.IdJsonMappingException; import io.a2a.spec.InvalidAgentResponseError; import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidParamsJsonMappingException; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.JSONRPCMessage; -import io.a2a.spec.JSONRPCRequest; -import io.a2a.spec.JSONRPCResponse; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTaskPushNotificationConfigResponse; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.ListTasksResponse; import io.a2a.spec.MethodNotFoundError; -import io.a2a.spec.MethodNotFoundJsonMappingException; import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendMessageResponse; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.UnsupportedOperationError; -import java.io.IOException; -import java.io.StringWriter; -import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; +import io.a2a.util.Utils; import org.jspecify.annotations.Nullable; -import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INTERNAL_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_AGENT_RESPONSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_PARAMS_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.INVALID_REQUEST_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.METHOD_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.PUSH_NOTIFICATION_NOT_SUPPORTED_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_CANCELABLE_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.TASK_NOT_FOUND_ERROR_CODE; -import static io.a2a.spec.A2AErrorCodes.UNSUPPORTED_OPERATION_ERROR_CODE; - -import io.a2a.json.JsonProcessingException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import static io.a2a.spec.A2AMethods.DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_METHOD; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_METHOD; +import static io.a2a.spec.A2AMethods.LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SEND_MESSAGE_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SUBSCRIBE_TO_TASK_METHOD; /** * Utilities for converting between JSON-RPC 2.0 messages and Protocol Buffer objects. @@ -150,8 +163,8 @@ * } * * @see ProtoUtils - * @see JSONRPCRequest - * @see JSONRPCResponse + * @see A2ARequest + * @see A2AResponse * @see JSON-RPC 2.0 Specification */ public class JSONRPCUtils { @@ -164,7 +177,7 @@ public class JSONRPCUtils { private static final Pattern EXTRACT_WRONG_TYPE = Pattern.compile("Expected (.*) but found \".*\""); static final String ERROR_MESSAGE = "Invalid request content: %s. Please verify the request matches the expected schema for this method."; - public static JSONRPCRequest parseRequestBody(String body) throws JsonMappingException, JsonProcessingException { + public static A2ARequest parseRequestBody(String body) throws JsonMappingException, JsonProcessingException { JsonElement jelement = JsonParser.parseString(body); JsonObject jsonRpc = jelement.getAsJsonObject(); if (!jsonRpc.has("method")) { @@ -176,65 +189,64 @@ public static JSONRPCRequest parseRequestBody(String body) throws JsonMapping Object id = getAndValidateId(jsonRpc); String method = jsonRpc.get("method").getAsString(); JsonElement paramsNode = jsonRpc.get("params"); - try { return parseMethodRequest(version, id, method, paramsNode); } catch (InvalidParamsError e) { - throw new InvalidParamsJsonMappingException(e.getMessage(), id); + throw new InvalidParamsJsonMappingException(Utils.defaultIfNull(e.getMessage(), "Invalid parameters"), id); } } - private static JSONRPCRequest parseMethodRequest(String version, Object id, String method, JsonElement paramsNode) throws InvalidParamsError, MethodNotFoundJsonMappingException, JsonProcessingException { + private static A2ARequest parseMethodRequest(String version, Object id, String method, JsonElement paramsNode) throws InvalidParamsError, MethodNotFoundJsonMappingException, JsonProcessingException { switch (method) { - case GetTaskRequest.METHOD -> { + case GET_TASK_METHOD -> { io.a2a.grpc.GetTaskRequest.Builder builder = io.a2a.grpc.GetTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetTaskRequest(version, id, ProtoUtils.FromProto.taskQueryParams(builder)); } - case CancelTaskRequest.METHOD -> { + case CANCEL_TASK_METHOD -> { io.a2a.grpc.CancelTaskRequest.Builder builder = io.a2a.grpc.CancelTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new CancelTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); } - case ListTasksRequest.METHOD -> { + case LIST_TASK_METHOD -> { io.a2a.grpc.ListTasksRequest.Builder builder = io.a2a.grpc.ListTasksRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new ListTasksRequest(version, id, ProtoUtils.FromProto.listTasksParams(builder)); } - case SetTaskPushNotificationConfigRequest.METHOD -> { + case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.SetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.SetTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new SetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.setTaskPushNotificationConfig(builder)); } - case GetTaskPushNotificationConfigRequest.METHOD -> { + case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.GetTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.GetTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.getTaskPushNotificationConfigParams(builder)); } - case SendMessageRequest.METHOD -> { + case SEND_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new SendMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } - case ListTaskPushNotificationConfigRequest.METHOD -> { + case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.ListTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new ListTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.listTaskPushNotificationConfigParams(builder)); } - case DeleteTaskPushNotificationConfigRequest.METHOD -> { + case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.Builder builder = io.a2a.grpc.DeleteTaskPushNotificationConfigRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new DeleteTaskPushNotificationConfigRequest(version, id, ProtoUtils.FromProto.deleteTaskPushNotificationConfigParams(builder)); } - case GetAuthenticatedExtendedCardRequest.METHOD -> { + case GET_EXTENDED_AGENT_CARD_METHOD -> { return new GetAuthenticatedExtendedCardRequest(version, id); } - case SendStreamingMessageRequest.METHOD -> { + case SEND_STREAMING_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageRequest.Builder builder = io.a2a.grpc.SendMessageRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new SendStreamingMessageRequest(version, id, ProtoUtils.FromProto.messageSendParams(builder)); } - case SubscribeToTaskRequest.METHOD -> { + case SUBSCRIBE_TO_TASK_METHOD -> { io.a2a.grpc.SubscribeToTaskRequest.Builder builder = io.a2a.grpc.SubscribeToTaskRequest.newBuilder(); parseRequestBody(paramsNode, builder, id); return new SubscribeToTaskRequest(version, id, ProtoUtils.FromProto.taskIdParams(builder)); @@ -258,7 +270,7 @@ public static StreamResponse parseResponseEvent(String body) throws JsonMappingE return builder.build(); } - public static JSONRPCResponse parseResponseBody(String body, String method) throws JsonMappingException, JsonProcessingException { + public static A2AResponse parseResponseBody(String body, String method) throws JsonMappingException, JsonProcessingException { JsonElement jelement = JsonParser.parseString(body); JsonObject jsonRpc = jelement.getAsJsonObject(); String version = getAndValidateJsonrpc(jsonRpc); @@ -268,32 +280,32 @@ public static JSONRPCResponse parseResponseBody(String body, String method) t return parseError(jsonRpc.getAsJsonObject("error"), id, method); } switch (method) { - case GetTaskRequest.METHOD -> { + case GET_TASK_METHOD -> { io.a2a.grpc.Task.Builder builder = io.a2a.grpc.Task.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetTaskResponse(id, ProtoUtils.FromProto.task(builder)); } - case CancelTaskRequest.METHOD -> { + case CANCEL_TASK_METHOD -> { io.a2a.grpc.Task.Builder builder = io.a2a.grpc.Task.newBuilder(); parseRequestBody(paramsNode, builder, id); return new CancelTaskResponse(id, ProtoUtils.FromProto.task(builder)); } - case ListTasksRequest.METHOD -> { + case LIST_TASK_METHOD -> { io.a2a.grpc.ListTasksResponse.Builder builder = io.a2a.grpc.ListTasksResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); return new ListTasksResponse(id, ProtoUtils.FromProto.listTasksResult(builder)); } - case SetTaskPushNotificationConfigRequest.METHOD -> { + case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(paramsNode, builder, id); return new SetTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); } - case GetTaskPushNotificationConfigRequest.METHOD -> { + case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.TaskPushNotificationConfig.Builder builder = io.a2a.grpc.TaskPushNotificationConfig.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.taskPushNotificationConfig(builder)); } - case SendMessageRequest.METHOD -> { + case SEND_MESSAGE_METHOD -> { io.a2a.grpc.SendMessageResponse.Builder builder = io.a2a.grpc.SendMessageResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); if (builder.hasMsg()) { @@ -301,15 +313,15 @@ public static JSONRPCResponse parseResponseBody(String body, String method) t } return new SendMessageResponse(id, ProtoUtils.FromProto.task(builder.getTask())); } - case ListTaskPushNotificationConfigRequest.METHOD -> { + case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { io.a2a.grpc.ListTaskPushNotificationConfigResponse.Builder builder = io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(); parseRequestBody(paramsNode, builder, id); return new ListTaskPushNotificationConfigResponse(id, ProtoUtils.FromProto.listTaskPushNotificationConfigResult(builder)); } - case DeleteTaskPushNotificationConfigRequest.METHOD -> { + case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new DeleteTaskPushNotificationConfigResponse(id); } - case GetAuthenticatedExtendedCardRequest.METHOD -> { + case GET_EXTENDED_AGENT_CARD_METHOD -> { io.a2a.grpc.AgentCard.Builder builder = io.a2a.grpc.AgentCard.newBuilder(); parseRequestBody(paramsNode, builder, id); return new GetAuthenticatedExtendedCardResponse(id, ProtoUtils.FromProto.agentCard(builder)); @@ -319,31 +331,31 @@ public static JSONRPCResponse parseResponseBody(String body, String method) t } } - public static JSONRPCResponse parseError(JsonObject error, Object id, String method) throws JsonMappingException { - JSONRPCError rpcError = processError(error); + public static A2AResponse parseError(JsonObject error, Object id, String method) throws JsonMappingException { + A2AError rpcError = processError(error); switch (method) { - case GetTaskRequest.METHOD -> { + case GET_TASK_METHOD -> { return new GetTaskResponse(id, rpcError); } - case CancelTaskRequest.METHOD -> { + case CANCEL_TASK_METHOD -> { return new CancelTaskResponse(id, rpcError); } - case ListTasksRequest.METHOD -> { + case LIST_TASK_METHOD -> { return new ListTasksResponse(id, rpcError); } - case SetTaskPushNotificationConfigRequest.METHOD -> { + case SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new SetTaskPushNotificationConfigResponse(id, rpcError); } - case GetTaskPushNotificationConfigRequest.METHOD -> { + case GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new GetTaskPushNotificationConfigResponse(id, rpcError); } - case SendMessageRequest.METHOD -> { + case SEND_MESSAGE_METHOD -> { return new SendMessageResponse(id, rpcError); } - case ListTaskPushNotificationConfigRequest.METHOD -> { + case LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new ListTaskPushNotificationConfigResponse(id, rpcError); } - case DeleteTaskPushNotificationConfigRequest.METHOD -> { + case DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD -> { return new DeleteTaskPushNotificationConfigResponse(id, rpcError); } default -> @@ -351,7 +363,7 @@ public static JSONRPCResponse parseError(JsonObject error, Object id, String } } - private static JSONRPCError processError(JsonObject error) { + private static A2AError processError(JsonObject error) { String message = error.has("message") ? error.get("message").getAsString() : null; Integer code = error.has("code") ? error.get("code").getAsInt() : null; String data = error.has("data") ? error.get("data").toString() : null; @@ -380,17 +392,17 @@ private static JSONRPCError processError(JsonObject error) { case TASK_NOT_FOUND_ERROR_CODE: return new TaskNotFoundError(code, message, data); default: - return new JSONRPCError(code, message, data); + return new A2AError(code, message, data); } } - return new JSONRPCError(code, message, data); + return new A2AError(code, message, data); } protected static void parseRequestBody(JsonElement jsonRpc, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { parseJsonString(jsonRpc.toString(), builder, id); } - public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, @Nullable Object id) throws JsonProcessingException { + public static void parseJsonString(String body, com.google.protobuf.Message.Builder builder, Object id) throws JsonProcessingException { try { JsonFormat.parser().merge(body, builder); } catch (InvalidProtocolBufferException e) { @@ -424,7 +436,7 @@ public static void parseJsonString(String body, com.google.protobuf.Message.Buil * @param id the request ID if it could be extracted, null otherwise * @return an appropriate JsonProcessingException subtype based on the error and ID availability */ - private static JsonProcessingException convertProtoBufExceptionToJsonProcessingException(InvalidProtocolBufferException e, @Nullable Object id) { + private static JsonProcessingException convertProtoBufExceptionToJsonProcessingException(InvalidProtocolBufferException e, Object id) { // Log the original exception for debugging purposes log.log(Level.FINE, "Converting protobuf parsing exception to JSON-RPC error. Request ID: {0}", id); log.log(Level.FINE, "Original proto exception details", e); @@ -448,12 +460,12 @@ private static JsonProcessingException convertProtoBufExceptionToJsonProcessingE Matcher matcher = EXTRACT_WRONG_TYPE.matcher(message); if (matcher.matches() && matcher.group(1) != null) { // ID is null -> use empty string sentinel value (see javadoc above) - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(matcher.group(1)), id == null ? "" : id); + return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(matcher.group(1)), Utils.defaultIfNull(id, "")); } matcher = EXTRACT_WRONG_VALUE.matcher(message); if (matcher.matches() && matcher.group(1) != null) { // ID is null -> use empty string sentinel value (see javadoc above) - return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(matcher.group(1)), id == null ? "" : id); + return new InvalidParamsJsonMappingException(ERROR_MESSAGE.formatted(matcher.group(1)), Utils.defaultIfNull(id, "")); } // Generic error - couldn't match specific patterns @@ -467,7 +479,7 @@ protected static String getAndValidateJsonrpc(JsonObject jsonRpc) throws JsonMap getIdIfPossible(jsonRpc)); } String version = jsonRpc.get("jsonrpc").getAsString(); - if (!JSONRPCMessage.JSONRPC_VERSION.equals(version)) { + if (!A2AMessage.JSONRPC_VERSION.equals(version)) { throw new IdJsonMappingException( "Unsupported JSON-RPC version: '" + version + "'. Expected version '2.0'", getIdIfPossible(jsonRpc)); @@ -558,7 +570,7 @@ public static String toJsonRPCResultResponse(Object requestId, com.google.protob } } - public static String toJsonRPCErrorResponse(Object requestId, JSONRPCError error) { + public static String toJsonRPCErrorResponse(Object requestId, A2AError error) { try (StringWriter result = new StringWriter(); JsonWriter output = GSON.newJsonWriter(result)) { output.beginObject(); output.name("jsonrpc").value("2.0"); diff --git a/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java b/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java index 6a0ac5409..b4e9a1755 100644 --- a/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java +++ b/spec-grpc/src/main/java/io/a2a/grpc/utils/ProtoUtils.java @@ -1,9 +1,10 @@ package io.a2a.grpc.utils; -import io.a2a.grpc.GetExtendedAgentCardRequest; -import io.a2a.grpc.StreamResponse; import java.util.ArrayList; import java.util.List; + +import io.a2a.grpc.GetExtendedAgentCardRequest; +import io.a2a.grpc.StreamResponse; import io.a2a.grpc.mapper.AgentCardMapper; import io.a2a.grpc.mapper.DeleteTaskPushNotificationConfigParamsMapper; import io.a2a.grpc.mapper.GetTaskPushNotificationConfigParamsMapper; @@ -22,16 +23,15 @@ import io.a2a.grpc.mapper.TaskQueryParamsMapper; import io.a2a.grpc.mapper.TaskStateMapper; import io.a2a.grpc.mapper.TaskStatusUpdateEventMapper; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.spec.AgentCard; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; import io.a2a.spec.EventKind; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; import io.a2a.spec.GetTaskPushNotificationConfigParams; import io.a2a.spec.InvalidParamsError; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.Message; import io.a2a.spec.MessageSendConfiguration; import io.a2a.spec.MessageSendParams; @@ -55,7 +55,7 @@ public static io.a2a.grpc.AgentCard agentCard(AgentCard agentCard) { return AgentCardMapper.INSTANCE.toProto(agentCard); } - public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard(GetAuthenticatedExtendedCardRequest request) { + public static io.a2a.grpc.GetExtendedAgentCardRequest extendedAgentCard() { return GetExtendedAgentCardRequest.newBuilder().build(); } diff --git a/spec-grpc/src/main/proto/a2a.proto b/spec-grpc/src/main/proto/a2a.proto index 7243ff40a..888fd18b8 100644 --- a/spec-grpc/src/main/proto/a2a.proto +++ b/spec-grpc/src/main/proto/a2a.proto @@ -2,8 +2,6 @@ syntax = "proto3"; package a2a.v1; -//From commit c196824396bb4af4c595f30e2c503a5ab1dbac4b - import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; @@ -11,6 +9,8 @@ import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; +//From commit c196824396bb4af4c595f30e2c503a5ab1dbac4b + option csharp_namespace = "A2a.V1"; option go_package = "google.golang.org/a2a/v1"; option java_multiple_files = true; diff --git a/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java b/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java index ba1496547..0619af352 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/mapper/StreamResponseMapperTest.java @@ -5,6 +5,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.Collections; + import io.a2a.spec.Artifact; import io.a2a.spec.Message; import io.a2a.spec.StreamingEventKind; @@ -14,7 +16,6 @@ import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; import io.a2a.spec.TextPart; -import java.util.Collections; import org.junit.jupiter.api.Test; public class StreamResponseMapperTest { diff --git a/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java b/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java index ffb048b28..61506c88e 100644 --- a/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java +++ b/spec-grpc/src/test/java/io/a2a/grpc/utils/JSONRPCUtilsTest.java @@ -1,23 +1,25 @@ package io.a2a.grpc.utils; import static io.a2a.grpc.utils.JSONRPCUtils.ERROR_MESSAGE; +import static io.a2a.spec.A2AMethods.GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; +import static io.a2a.spec.A2AMethods.SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import io.a2a.json.JsonProcessingException; import com.google.gson.JsonSyntaxException; -import io.a2a.json.JsonMappingException; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.json.InvalidParamsJsonMappingException; +import io.a2a.jsonrpc.common.json.JsonMappingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.wrappers.A2ARequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; import io.a2a.spec.InvalidParamsError; -import io.a2a.spec.InvalidParamsJsonMappingException; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCRequest; import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; import io.a2a.spec.TaskPushNotificationConfig; import org.junit.jupiter.api.Test; @@ -47,7 +49,7 @@ public void testParseSetTaskPushNotificationConfigRequest_ValidProtoFormat() thr } """; - JSONRPCRequest request = JSONRPCUtils.parseRequestBody(validRequest); + A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest); assertNotNull(request); assertInstanceOf(SetTaskPushNotificationConfigRequest.class, request); @@ -76,7 +78,7 @@ public void testParseGetTaskPushNotificationConfigRequest_ValidProtoFormat() thr } """; - JSONRPCRequest request = JSONRPCUtils.parseRequestBody(validRequest); + A2ARequest request = JSONRPCUtils.parseRequestBody(validRequest); assertNotNull(request); assertInstanceOf(GetTaskPushNotificationConfigRequest.class, request); @@ -285,7 +287,7 @@ public void testGenerateSetTaskPushNotificationConfigResponse_Success() throws E """; SetTaskPushNotificationConfigResponse response = - (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, SetTaskPushNotificationConfigRequest.METHOD); + (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(1, response.getId()); @@ -311,7 +313,7 @@ public void testGenerateGetTaskPushNotificationConfigResponse_Success() throws E """; GetTaskPushNotificationConfigResponse response = - (GetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, GetTaskPushNotificationConfigRequest.METHOD); + (GetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(responseJson, GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(2, response.getId()); @@ -334,7 +336,7 @@ public void testParseErrorResponse_InvalidParams() throws Exception { """; SetTaskPushNotificationConfigResponse response = - (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SetTaskPushNotificationConfigRequest.METHOD); + (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(5, response.getId()); @@ -358,7 +360,7 @@ public void testParseErrorResponse_ParseError() throws Exception { """; SetTaskPushNotificationConfigResponse response = - (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SetTaskPushNotificationConfigRequest.METHOD); + (SetTaskPushNotificationConfigResponse) JSONRPCUtils.parseResponseBody(errorResponse, SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD); assertNotNull(response); assertEquals(6, response.getId()); diff --git a/spec/src/main/java/io/a2a/spec/A2AError.java b/spec/src/main/java/io/a2a/spec/A2AError.java index 122b26a0d..4bbc8917b 100644 --- a/spec/src/main/java/io/a2a/spec/A2AError.java +++ b/spec/src/main/java/io/a2a/spec/A2AError.java @@ -1,5 +1,7 @@ package io.a2a.spec; +import io.a2a.util.Assert; + /** * Marker interface for A2A Protocol error events. *

      @@ -7,7 +9,7 @@ * in the A2A Protocol's event stream. All protocol-level errors implement this interface, * enabling uniform error handling across both streaming and non-streaming communication. *

      - * A2A errors typically extend {@link JSONRPCError} to provide JSON-RPC 2.0 compliant + * A2A errors typically extend {@link A2AError} to provide JSON-RPC 2.0 compliant * error responses with standard error codes, messages, and optional additional data. *

      * Common implementations include: @@ -21,9 +23,68 @@ *

    * * @see Event for the base event interface - * @see JSONRPCError for the base error implementation + * @see A2AError for the base error implementation * @see JSON-RPC 2.0 Error Object * @see A2A Protocol Specification */ -public interface A2AError extends Event { +public class A2AError extends RuntimeException implements Event { + /** + * The numeric error code (see JSON-RPC 2.0 spec for standard codes). + */ + private final Integer code; + + /** + * Additional error information (structure defined by the error code). + */ + private final Object data; + + /** + * Constructs a JSON-RPC error with the specified code, message, and optional data. + *

    + * This constructor is used by Jackson for JSON deserialization. + * + * @param code the numeric error code (required, see JSON-RPC 2.0 spec for standard codes) + * @param message the human-readable error message (required) + * @param data additional error information, structure defined by the error code (optional) + * @throws IllegalArgumentException if code or message is null + */ + public A2AError(Integer code, String message, Object data) { + super(message); + Assert.checkNotNullParam("code", code); + Assert.checkNotNullParam("message", message); + this.code = code; + this.data = data; + } + + /** + * Gets the numeric error code indicating the error type. + *

    + * Standard JSON-RPC 2.0 error codes: + *

      + *
    • -32700: Parse error
    • + *
    • -32600: Invalid Request
    • + *
    • -32601: Method not found
    • + *
    • -32602: Invalid params
    • + *
    • -32603: Internal error
    • + *
    • -32000 to -32099: Server error (implementation-defined)
    • + *
    + * + * @return the error code + */ + public Integer getCode() { + return code; + } + + /** + * Gets additional information about the error. + *

    + * The structure and type of the data field is defined by the specific error code. + * It may contain detailed debugging information, validation errors, or other + * context-specific data to help diagnose the error. + * + * @return the error data, or null if not provided + */ + public Object getData() { + return data; + } } diff --git a/spec/src/main/java/io/a2a/spec/A2AMethods.java b/spec/src/main/java/io/a2a/spec/A2AMethods.java new file mode 100644 index 000000000..0ffdf6e30 --- /dev/null +++ b/spec/src/main/java/io/a2a/spec/A2AMethods.java @@ -0,0 +1,17 @@ + +package io.a2a.spec; + +public interface A2AMethods { + String CANCEL_TASK_METHOD = "CancelTask"; + String DELETE_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "DeleteTaskPushNotificationConfig"; + String GET_EXTENDED_AGENT_CARD_METHOD = "GetExtendedAgentCard"; + String GET_TASK_METHOD = "GetTask"; + String GET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "GetTaskPushNotificationConfig"; + String LIST_TASK_METHOD = "ListTasks"; + String LIST_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "ListTaskPushNotificationConfig"; + String SEND_MESSAGE_METHOD = "SendMessage"; + String SEND_STREAMING_MESSAGE_METHOD = "SendStreamingMessage"; + String SET_TASK_PUSH_NOTIFICATION_CONFIG_METHOD = "SetTaskPushNotificationConfig"; + String SUBSCRIBE_TO_TASK_METHOD = "SubscribeToTask"; + +} diff --git a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java b/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java index 01fc23509..a69c9a4ad 100644 --- a/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/APIKeySecurityScheme.java @@ -2,8 +2,6 @@ import io.a2a.util.Assert; -import static io.a2a.spec.APIKeySecurityScheme.API_KEY; - /** * API key security scheme for agent authentication. *

    diff --git a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java b/spec/src/main/java/io/a2a/spec/AgentCardSignature.java index aac74a412..cb6bc5c77 100644 --- a/spec/src/main/java/io/a2a/spec/AgentCardSignature.java +++ b/spec/src/main/java/io/a2a/spec/AgentCardSignature.java @@ -1,8 +1,8 @@ package io.a2a.spec; -import com.google.gson.annotations.SerializedName; import java.util.Map; +import com.google.gson.annotations.SerializedName; import io.a2a.util.Assert; /** diff --git a/spec/src/main/java/io/a2a/spec/AuthenticatedExtendedCardNotConfiguredError.java b/spec/src/main/java/io/a2a/spec/AuthenticatedExtendedCardNotConfiguredError.java index de99e54da..52650dc1f 100644 --- a/spec/src/main/java/io/a2a/spec/AuthenticatedExtendedCardNotConfiguredError.java +++ b/spec/src/main/java/io/a2a/spec/AuthenticatedExtendedCardNotConfiguredError.java @@ -7,9 +7,8 @@ /** * A2A Protocol error indicating that the agent does not have an authenticated extended card configured. *

    - * This error is returned when a client attempts to retrieve an authenticated extended agent card - * via {@link GetAuthenticatedExtendedCardRequest}, but the agent has not configured authentication-protected - * extended card information. + * This error is returned when a client attempts to retrieve an authenticated extended agent card, + * but the agent has not configured authentication-protected extended card information. *

    * Extended cards may contain additional agent metadata, capabilities, or configuration that * should only be accessible to authenticated clients. Agents that don't implement this feature @@ -25,11 +24,10 @@ * } * } * - * @see GetAuthenticatedExtendedCardRequest for retrieving authenticated extended cards * @see AgentCard for the base agent card structure * @see A2A Protocol Specification */ -public class AuthenticatedExtendedCardNotConfiguredError extends JSONRPCError { +public class AuthenticatedExtendedCardNotConfiguredError extends A2AError { /** * Constructs an error for agents that don't support authenticated extended card retrieval. diff --git a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java index b895531c6..c4db756a4 100644 --- a/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/AuthorizationCodeOAuthFlow.java @@ -2,7 +2,6 @@ import java.util.Map; - import io.a2a.util.Assert; /** diff --git a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java b/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java index 88ce8a127..f248eaa70 100644 --- a/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/ClientCredentialsOAuthFlow.java @@ -3,7 +3,6 @@ import java.util.Map; - import io.a2a.util.Assert; /** diff --git a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java index 9bd10192a..a696a891a 100644 --- a/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/ContentTypeNotSupportedError.java @@ -1,9 +1,7 @@ package io.a2a.spec; -import static io.a2a.util.Utils.defaultIfNull; - - import static io.a2a.spec.A2AErrorCodes.CONTENT_TYPE_NOT_SUPPORTED_ERROR_CODE; +import static io.a2a.util.Utils.defaultIfNull; /** * A2A Protocol error indicating incompatibility between requested content types and agent capabilities. @@ -38,7 +36,7 @@ * @see MessageSendConfiguration for client content type preferences * @see A2A Protocol Specification */ -public class ContentTypeNotSupportedError extends JSONRPCError { +public class ContentTypeNotSupportedError extends A2AError { /** * Constructs a content type not supported error. diff --git a/spec/src/main/java/io/a2a/spec/DataPart.java b/spec/src/main/java/io/a2a/spec/DataPart.java index d44e87151..163225429 100644 --- a/spec/src/main/java/io/a2a/spec/DataPart.java +++ b/spec/src/main/java/io/a2a/spec/DataPart.java @@ -4,8 +4,6 @@ import io.a2a.util.Assert; -import static io.a2a.util.Utils.SPEC_VERSION_1_0; - /** * Represents a structured data content part within a {@link Message} or {@link Artifact}. diff --git a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java index 9745ccf2d..75faf2e54 100644 --- a/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/DeleteTaskPushNotificationConfigParams.java @@ -13,7 +13,6 @@ * @param id the task identifier (required) * @param pushNotificationConfigId the specific configuration ID to delete (required) * @param tenant optional tenant, provided as a path parameter. - * @see DeleteTaskPushNotificationConfigRequest for the request using these parameters * @see A2A Protocol Specification */ public record DeleteTaskPushNotificationConfigParams(String id, String pushNotificationConfigId, String tenant) { diff --git a/spec/src/main/java/io/a2a/spec/FilePart.java b/spec/src/main/java/io/a2a/spec/FilePart.java index a1835109c..79b63fe64 100644 --- a/spec/src/main/java/io/a2a/spec/FilePart.java +++ b/spec/src/main/java/io/a2a/spec/FilePart.java @@ -3,8 +3,6 @@ import io.a2a.util.Assert; -import static io.a2a.util.Utils.SPEC_VERSION_1_0; - /** * Represents a file content part within a {@link Message} or {@link Artifact}. diff --git a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java index 225aa4071..36f2db3fb 100644 --- a/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/GetTaskPushNotificationConfigParams.java @@ -14,7 +14,6 @@ * @param id the task identifier (required) * @param pushNotificationConfigId optional specific configuration ID to retrieve * @param tenant optional tenant, provided as a path parameter. - * @see GetTaskPushNotificationConfigRequest for the request using these parameters * @see TaskPushNotificationConfig for the returned configuration structure * @see A2A Protocol Specification */ diff --git a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java index 76620d868..54858562f 100644 --- a/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/HTTPAuthSecurityScheme.java @@ -2,9 +2,6 @@ import io.a2a.util.Assert; -import static io.a2a.spec.HTTPAuthSecurityScheme.HTTP; -import static io.a2a.util.Utils.SPEC_VERSION_1_0; - /** * HTTP authentication security scheme for agent authentication. *

    diff --git a/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java b/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java index 93d3f15ac..06341ab2b 100644 --- a/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java +++ b/spec/src/main/java/io/a2a/spec/ImplicitOAuthFlow.java @@ -2,7 +2,6 @@ import java.util.Map; - import io.a2a.util.Assert; /** diff --git a/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java b/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java deleted file mode 100644 index 386a59118..000000000 --- a/spec/src/main/java/io/a2a/spec/IntegerJsonrpcId.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.a2a.spec; - -/** - * Integer-based implementation of JSON-RPC request/response correlation identifier. - *

    - * This class represents a JSON-RPC ID that uses an Integer value for correlation - * between requests and responses. According to the JSON-RPC 2.0 specification, - * Number IDs are one of the valid identifier types (along with String and NULL). - *

    - * Integer IDs are commonly used when: - *

      - *
    • Sequential request numbering is desired
    • - *
    • Memory efficiency is important (integers are smaller than strings)
    • - *
    • Simple monotonic correlation is sufficient
    • - *
    - * - * @see JsonrpcId - * @see StringJsonrpcId - * @see JSON-RPC 2.0 Request Object - */ -public class IntegerJsonrpcId implements JsonrpcId { -} diff --git a/spec/src/main/java/io/a2a/spec/InternalError.java b/spec/src/main/java/io/a2a/spec/InternalError.java index 72f4f825e..99aa71220 100644 --- a/spec/src/main/java/io/a2a/spec/InternalError.java +++ b/spec/src/main/java/io/a2a/spec/InternalError.java @@ -23,11 +23,9 @@ * } * } * - * @see JSONRPCError for the base error class - * @see A2AError for the error marker interface * @see JSON-RPC 2.0 Error Codes */ -public class InternalError extends JSONRPCError { +public class InternalError extends A2AError { /** * Constructs an internal error with full parameters. diff --git a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java index 187260bd9..303a3f548 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidAgentResponseError.java @@ -33,11 +33,9 @@ * } * } * - * @see JSONRPCResponse for response structure - * @see SendMessageResponse for message send response * @see A2A Protocol Specification */ -public class InvalidAgentResponseError extends JSONRPCError { +public class InvalidAgentResponseError extends A2AError { /** * Constructs an invalid agent response error. diff --git a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java index 4556c8fff..a7f3476c3 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidParamsError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidParamsError.java @@ -26,11 +26,9 @@ * throw new InvalidParamsError("taskId parameter is required"); * } * - * @see JSONRPCError for the base error class - * @see A2AError for the error marker interface * @see JSON-RPC 2.0 Error Codes */ -public class InvalidParamsError extends JSONRPCError { +public class InvalidParamsError extends A2AError { /** * Constructs an invalid params error with full parameters. diff --git a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java index 7f64a0ccc..98d0f65f7 100644 --- a/spec/src/main/java/io/a2a/spec/InvalidRequestError.java +++ b/spec/src/main/java/io/a2a/spec/InvalidRequestError.java @@ -27,11 +27,9 @@ * throw new InvalidRequestError("Missing 'method' field in request"); * } * - * @see JSONRPCError for the base error class - * @see A2AError for the error marker interface * @see JSON-RPC 2.0 Error Codes */ -public class InvalidRequestError extends JSONRPCError { +public class InvalidRequestError extends A2AError { /** * Constructs an invalid request error with default message. diff --git a/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java b/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java deleted file mode 100644 index 8823f9bd3..000000000 --- a/spec/src/main/java/io/a2a/spec/JSONErrorResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package io.a2a.spec; - -/** - * A simplified error response wrapper for non-JSON-RPC error scenarios. - *

    - * This record provides a lightweight error response format for cases where - * a full JSON-RPC error structure is not appropriate, such as HTTP-level - * errors or transport-layer failures. - *

    - * Unlike {@link JSONRPCErrorResponse}, this is not part of the JSON-RPC 2.0 - * specification but serves as a utility for simpler error reporting in the - * A2A Java SDK implementation. - * - * @param error a human-readable error message - * @see JSONRPCErrorResponse - * @see JSONRPCError - */ -public record JSONErrorResponse(String error) { -} diff --git a/spec/src/main/java/io/a2a/spec/JSONParseError.java b/spec/src/main/java/io/a2a/spec/JSONParseError.java index 24c4c67d2..74da3ddf5 100644 --- a/spec/src/main/java/io/a2a/spec/JSONParseError.java +++ b/spec/src/main/java/io/a2a/spec/JSONParseError.java @@ -21,12 +21,12 @@ * } * } * - * @see JSONRPCError for the base error class + * @see A2AError for the base error class * @see A2AError for the error marker interface * @see InvalidRequestError for structurally valid but invalid requests * @see JSON-RPC 2.0 Error Codes */ -public class JSONParseError extends JSONRPCError implements A2AError { +public class JSONParseError extends A2AError { /** * Constructs a JSON parse error with default message. diff --git a/spec/src/main/java/io/a2a/spec/JSONRPCError.java b/spec/src/main/java/io/a2a/spec/JSONRPCError.java deleted file mode 100644 index 860fde68d..000000000 --- a/spec/src/main/java/io/a2a/spec/JSONRPCError.java +++ /dev/null @@ -1,97 +0,0 @@ -package io.a2a.spec; - - -import io.a2a.util.Assert; - -/** - * Represents a JSON-RPC 2.0 error object as defined in the JSON-RPC 2.0 specification. - *

    - * This class encapsulates error information returned in JSON-RPC error responses. - * According to the JSON-RPC 2.0 specification, an error object must contain: - *

      - *
    • {@code code} - A number indicating the error type (required)
    • - *
    • {@code message} - A short description of the error (required)
    • - *
    • {@code data} - Additional information about the error (optional)
    • - *
    - *

    - * This class implements {@link Event} to allow errors to be streamed to clients, - * and {@link A2AError} to integrate with the A2A Protocol's error handling system. - * It extends {@link Error} to provide standard Java error semantics with a message. - *

    - * Standard error codes are defined in the JSON-RPC 2.0 specification: - *

      - *
    • -32700: Parse error
    • - *
    • -32600: Invalid Request
    • - *
    • -32601: Method not found
    • - *
    • -32602: Invalid params
    • - *
    • -32603: Internal error
    • - *
    • -32000 to -32099: Server error (implementation-defined)
    • - *
    - * - * @see Event - * @see A2AError - * @see JSONRPCErrorResponse - * @see JSON-RPC 2.0 Error Object - */ -public class JSONRPCError extends Error implements Event, A2AError { - - /** - * The numeric error code (see JSON-RPC 2.0 spec for standard codes). - */ - private final Integer code; - - /** - * Additional error information (structure defined by the error code). - */ - private final Object data; - - /** - * Constructs a JSON-RPC error with the specified code, message, and optional data. - *

    - * This constructor is used by Jackson for JSON deserialization. - * - * @param code the numeric error code (required, see JSON-RPC 2.0 spec for standard codes) - * @param message the human-readable error message (required) - * @param data additional error information, structure defined by the error code (optional) - * @throws IllegalArgumentException if code or message is null - */ - public JSONRPCError(Integer code, String message, Object data) { - super(message); - Assert.checkNotNullParam("code", code); - Assert.checkNotNullParam("message", message); - this.code = code; - this.data = data; - } - - /** - * Gets the numeric error code indicating the error type. - *

    - * Standard JSON-RPC 2.0 error codes: - *

      - *
    • -32700: Parse error
    • - *
    • -32600: Invalid Request
    • - *
    • -32601: Method not found
    • - *
    • -32602: Invalid params
    • - *
    • -32603: Internal error
    • - *
    • -32000 to -32099: Server error (implementation-defined)
    • - *
    - * - * @return the error code - */ - public Integer getCode() { - return code; - } - - /** - * Gets additional information about the error. - *

    - * The structure and type of the data field is defined by the specific error code. - * It may contain detailed debugging information, validation errors, or other - * context-specific data to help diagnose the error. - * - * @return the error data, or null if not provided - */ - public Object getData() { - return data; - } -} diff --git a/spec/src/main/java/io/a2a/spec/JsonrpcId.java b/spec/src/main/java/io/a2a/spec/JsonrpcId.java deleted file mode 100644 index 152c2a5b1..000000000 --- a/spec/src/main/java/io/a2a/spec/JsonrpcId.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.a2a.spec; - -/** - * Marker interface for JSON-RPC request/response correlation identifiers. - *

    - * According to the JSON-RPC 2.0 specification, the {@code id} field must be - * a String, Number, or NULL value. This interface serves as a type marker - * for implementations that represent valid JSON-RPC IDs. - *

    - * The A2A Java SDK provides two concrete implementations: - *

      - *
    • {@link StringJsonrpcId} - For string-based identifiers
    • - *
    • {@link IntegerJsonrpcId} - For numeric identifiers
    • - *
    - *

    - * Null IDs are also valid and represent notifications (requests that do not - * expect a response). - * - * @see StringJsonrpcId - * @see IntegerJsonrpcId - * @see JSON-RPC 2.0 Request Object - */ -public interface JsonrpcId { -} diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java index 09967e378..f339afd88 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigParams.java @@ -10,7 +10,6 @@ * * @param id the task identifier (required) * @param tenant optional tenant, provided as a path parameter. - * @see ListTaskPushNotificationConfigRequest for the request using these parameters * @see TaskPushNotificationConfig for the configuration structure * @see A2A Protocol Specification */ diff --git a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java index 193b3ea9b..1ae125713 100644 --- a/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java +++ b/spec/src/main/java/io/a2a/spec/ListTaskPushNotificationConfigResult.java @@ -1,10 +1,10 @@ package io.a2a.spec; +import java.util.List; + import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; -import java.util.List; - /** * Result of listing push notification configurations for a task with pagination support. * diff --git a/spec/src/main/java/io/a2a/spec/ListTasksParams.java b/spec/src/main/java/io/a2a/spec/ListTasksParams.java index 4e2cc6432..6813dcf45 100644 --- a/spec/src/main/java/io/a2a/spec/ListTasksParams.java +++ b/spec/src/main/java/io/a2a/spec/ListTasksParams.java @@ -1,10 +1,10 @@ package io.a2a.spec; +import java.time.Instant; + import io.a2a.util.Assert; import org.jspecify.annotations.Nullable; -import java.time.Instant; - /** * Parameters for listing tasks with optional filtering and pagination. * diff --git a/spec/src/main/java/io/a2a/spec/MessageSendParams.java b/spec/src/main/java/io/a2a/spec/MessageSendParams.java index 4dca5f806..1dcb6dd61 100644 --- a/spec/src/main/java/io/a2a/spec/MessageSendParams.java +++ b/spec/src/main/java/io/a2a/spec/MessageSendParams.java @@ -8,8 +8,7 @@ * Parameters for sending a message to an agent in the A2A Protocol. *

    * This record encapsulates the message content, optional configuration, and metadata for - * agent task requests. It is used by both {@link SendMessageRequest} and - * {@link SendStreamingMessageRequest} to define what message to send and how to process it. + * agent task requests. It is used to define what message to send and how to process it. *

    * The message can create a new task, continue an existing task (if it contains a task ID), * or restart a task depending on the agent's implementation and the message context. @@ -18,8 +17,6 @@ * @param configuration optional configuration for message processing behavior * @param metadata optional arbitrary key-value metadata for the request * @param tenant optional tenant, provided as a path parameter. - * @see SendMessageRequest for non-streaming message delivery - * @see SendStreamingMessageRequest for streaming message delivery * @see MessageSendConfiguration for available configuration options * @see A2A Protocol Specification */ diff --git a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java index c56bbcf1d..e38f7a605 100644 --- a/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/MethodNotFoundError.java @@ -18,11 +18,9 @@ * throw new MethodNotFoundError(); * } * - * @see JSONRPCError for the base error class - * @see A2AError for the error marker interface * @see JSON-RPC 2.0 Error Codes */ -public class MethodNotFoundError extends JSONRPCError { +public class MethodNotFoundError extends A2AError { /** * Constructs error with all parameters. diff --git a/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java b/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java index 659df3c7a..86480258b 100644 --- a/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/MutualTLSSecurityScheme.java @@ -1,7 +1,5 @@ package io.a2a.spec; -import static io.a2a.spec.MutualTLSSecurityScheme.MUTUAL_TLS; - /** * Mutual TLS (mTLS) security scheme for agent authentication. *

    diff --git a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java index ee6557efc..f3179cc23 100644 --- a/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/OAuth2SecurityScheme.java @@ -2,8 +2,6 @@ import io.a2a.util.Assert; -import static io.a2a.spec.OAuth2SecurityScheme.OAUTH2; - /** * OAuth 2.0 security scheme for agent authentication. *

    diff --git a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java index 0ba446cad..e7dfcfab3 100644 --- a/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/OpenIdConnectSecurityScheme.java @@ -2,8 +2,6 @@ import io.a2a.util.Assert; -import static io.a2a.spec.OpenIdConnectSecurityScheme.OPENID_CONNECT; - /** * OpenID Connect security scheme for agent authentication. *

    diff --git a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java index 0dd571955..1a336cc00 100644 --- a/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java +++ b/spec/src/main/java/io/a2a/spec/PushNotificationNotSupportedError.java @@ -7,8 +7,7 @@ * A2A Protocol error indicating that the agent does not support push notifications. *

    * This error is returned when a client attempts push notification operations - * (such as {@link SetTaskPushNotificationConfigRequest}) on an agent that has - * {@link AgentCapabilities#pushNotifications()} set to {@code false}. + * on an agent that has {@link AgentCapabilities#pushNotifications()} set to {@code false}. *

    * Push notifications allow agents to proactively send task updates to clients via * HTTP callbacks. Agents that don't support this capability will return this error @@ -24,11 +23,10 @@ * } * * @see AgentCapabilities#pushNotifications() for push notification capability - * @see SetTaskPushNotificationConfigRequest for configuring push notifications * @see TaskPushNotificationConfig for push notification configuration * @see A2A Protocol Specification */ -public class PushNotificationNotSupportedError extends JSONRPCError { +public class PushNotificationNotSupportedError extends A2AError { /** * Constructs error with default message. diff --git a/spec/src/main/java/io/a2a/spec/SecurityScheme.java b/spec/src/main/java/io/a2a/spec/SecurityScheme.java index 2121a636e..322262eb9 100644 --- a/spec/src/main/java/io/a2a/spec/SecurityScheme.java +++ b/spec/src/main/java/io/a2a/spec/SecurityScheme.java @@ -1,7 +1,5 @@ package io.a2a.spec; -import static io.a2a.spec.APIKeySecurityScheme.API_KEY; - /** * Base interface for security schemes used to authenticate access to agent endpoints. *

    diff --git a/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java b/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java deleted file mode 100644 index 9a033a979..000000000 --- a/spec/src/main/java/io/a2a/spec/StringJsonrpcId.java +++ /dev/null @@ -1,22 +0,0 @@ -package io.a2a.spec; - -/** - * String-based implementation of JSON-RPC request/response correlation identifier. - *

    - * This class represents a JSON-RPC ID that uses a String value for correlation - * between requests and responses. According to the JSON-RPC 2.0 specification, - * String IDs are one of the valid identifier types (along with Number and NULL). - *

    - * String IDs are commonly used when: - *

      - *
    • Client-generated correlation requires UUID or similar format
    • - *
    • IDs need to encode additional context or metadata
    • - *
    • Compatibility with systems that use string-based correlation
    • - *
    - * - * @see JsonrpcId - * @see IntegerJsonrpcId - * @see JSON-RPC 2.0 Request Object - */ -public class StringJsonrpcId implements JsonrpcId { -} diff --git a/spec/src/main/java/io/a2a/spec/TaskIdParams.java b/spec/src/main/java/io/a2a/spec/TaskIdParams.java index 584cca60c..d35eb37d9 100644 --- a/spec/src/main/java/io/a2a/spec/TaskIdParams.java +++ b/spec/src/main/java/io/a2a/spec/TaskIdParams.java @@ -6,13 +6,10 @@ * Parameters containing a task identifier for task-related operations. *

    * This simple parameter record is used by operations that only need a task ID, - * such as {@link CancelTaskRequest}, {@link SubscribeToTaskRequest}, and similar - * task-specific requests. It optionally includes metadata for additional context. + * and similar task-specific requests. It optionally includes metadata for additional context. * * @param id the unique task identifier (required) * @param tenant optional tenant, provided as a path parameter. - * @see CancelTaskRequest for task cancellation - * @see SubscribeToTaskRequest for task resubscription * @see A2A Protocol Specification */ public record TaskIdParams(String id, String tenant) { diff --git a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java index ad39cda16..86e7887e3 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotCancelableError.java @@ -6,7 +6,7 @@ /** * A2A Protocol error indicating that a task cannot be canceled in its current state. *

    - * This error is returned when a client attempts to cancel a task via {@link CancelTaskRequest} + * This error is returned when a client attempts to cancel a task * but the task is in a terminal state ({@link TaskState#COMPLETED}, {@link TaskState#FAILED}, * {@link TaskState#CANCELED}) where cancellation is not applicable. *

    @@ -25,12 +25,11 @@ * } * } * - * @see CancelTaskRequest for task cancellation * @see TaskState for task state definitions * @see TaskStatus#state() for current task state * @see A2A Protocol Specification */ -public class TaskNotCancelableError extends JSONRPCError { +public class TaskNotCancelableError extends A2AError { /** * Constructs error with default message. diff --git a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java index 4366db5b8..b1dd902d5 100644 --- a/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java +++ b/spec/src/main/java/io/a2a/spec/TaskNotFoundError.java @@ -6,8 +6,7 @@ /** * A2A Protocol error indicating that the requested task ID does not exist. *

    - * This error is returned when a client attempts to perform operations on a task (such as - * {@link GetTaskRequest}, {@link CancelTaskRequest}, or push notification operations) using + * This error is returned when a client attempts to perform operations on a task using * a task ID that is not found in the server's task store. *

    * Common causes: @@ -29,11 +28,9 @@ * } * * @see Task for task object definition - * @see GetTaskRequest for task retrieval - * @see CancelTaskRequest for task cancellation * @see A2A Protocol Specification */ -public class TaskNotFoundError extends JSONRPCError { +public class TaskNotFoundError extends A2AError { /** * Constructs error with default message. diff --git a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java index 794a29e2a..cf57a6f3c 100644 --- a/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java +++ b/spec/src/main/java/io/a2a/spec/TaskPushNotificationConfig.java @@ -17,7 +17,6 @@ * @param taskId the unique identifier of the task to receive push notifications for (required) * @param pushNotificationConfig the push notification endpoint and authentication configuration (required) * @see PushNotificationConfig for notification endpoint details - * @see SetTaskPushNotificationConfigRequest for setting push notifications * @see A2A Protocol Specification */ public record TaskPushNotificationConfig(String taskId, PushNotificationConfig pushNotificationConfig, @Nullable String tenant) { diff --git a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java index 2a34a2e03..8dc872bba 100644 --- a/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java +++ b/spec/src/main/java/io/a2a/spec/TaskStatusUpdateEvent.java @@ -1,8 +1,8 @@ package io.a2a.spec; -import com.google.gson.annotations.SerializedName; import java.util.Map; +import com.google.gson.annotations.SerializedName; import io.a2a.util.Assert; /** diff --git a/spec/src/main/java/io/a2a/spec/TextPart.java b/spec/src/main/java/io/a2a/spec/TextPart.java index 57adef574..4ab51f217 100644 --- a/spec/src/main/java/io/a2a/spec/TextPart.java +++ b/spec/src/main/java/io/a2a/spec/TextPart.java @@ -3,8 +3,6 @@ import io.a2a.util.Assert; -import static io.a2a.util.Utils.SPEC_VERSION_1_0; - /** * Represents a plain text content part within a {@link Message} or {@link Artifact}. diff --git a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java index b4bebd1d8..da2231e30 100644 --- a/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java +++ b/spec/src/main/java/io/a2a/spec/UnsupportedOperationError.java @@ -31,7 +31,7 @@ * @see MethodNotFoundError for unknown method errors * @see A2A Protocol Specification */ -public class UnsupportedOperationError extends JSONRPCError { +public class UnsupportedOperationError extends A2AError { /** * Constructs error with all parameters. diff --git a/spec/src/main/java/io/a2a/util/Utils.java b/spec/src/main/java/io/a2a/util/Utils.java index 858737375..ca0610b1f 100644 --- a/spec/src/main/java/io/a2a/util/Utils.java +++ b/spec/src/main/java/io/a2a/util/Utils.java @@ -1,24 +1,21 @@ package io.a2a.util; +import static io.a2a.util.Assert.checkNotNullParam; + import java.util.ArrayList; import java.util.List; +import java.util.logging.Logger; import com.google.gson.Gson; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCard; import io.a2a.spec.AgentInterface; - import io.a2a.spec.Artifact; +import io.a2a.spec.Part; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; -import io.a2a.spec.Part; -import java.util.logging.Logger; import org.jspecify.annotations.Nullable; -import static io.a2a.util.Assert.checkNotNullParam; - /** * Utility class providing common helper methods for A2A Protocol operations. *

    @@ -46,21 +43,6 @@ public class Utils { */ public static final String SPEC_VERSION_1_0 = "1.0"; - /** - * Deserializes JSON string into a typed object using Gson. - *

    - * This method uses the pre-configured {@link JsonUtil#fromJson(String, Class)} to parse JSON. - * - * @param the target type - * @param data JSON string to deserialize - * @param typeRef class reference specifying the target type - * @return deserialized object of type T - * @throws JsonProcessingException if JSON parsing fails - */ - public static T unmarshalFrom(String data, Class typeRef) throws JsonProcessingException { - return JsonUtil.fromJson(data, typeRef); - } - /** * Returns the provided value if non-null, otherwise returns the default value. *

    @@ -73,10 +55,7 @@ public static T unmarshalFrom(String data, Class typeRef) throws JsonProc * @return value if non-null, otherwise defaultValue */ public static T defaultIfNull(@Nullable T value, T defaultValue) { - if (value == null) { - return defaultValue; - } - return value; + return value == null ? defaultValue : value; } /** diff --git a/spec/src/main/java/io/a2a/util/package-info.java b/spec/src/main/java/io/a2a/util/package-info.java new file mode 100644 index 000000000..769e16337 --- /dev/null +++ b/spec/src/main/java/io/a2a/util/package-info.java @@ -0,0 +1,5 @@ +@NullMarked +package io.a2a.util; + +import org.jspecify.annotations.NullMarked; + diff --git a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java b/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java index 0adedad9a..d1f5af5a6 100644 --- a/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java +++ b/tck/src/main/java/io/a2a/tck/server/AgentExecutorProducer.java @@ -8,7 +8,7 @@ import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; import io.a2a.spec.Task; import io.a2a.spec.TaskNotCancelableError; import io.a2a.spec.TaskState; @@ -27,7 +27,7 @@ public AgentExecutor agentExecutor() { private static class FireAndForgetAgentExecutor implements AgentExecutor { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { Task task = context.getTask(); if (task == null) { @@ -70,7 +70,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { System.out.println("====> task cancel request received"); Task task = context.getTask(); if (task == null) { diff --git a/tests/server-common/pom.xml b/tests/server-common/pom.xml index da377b10a..870c74fcc 100644 --- a/tests/server-common/pom.xml +++ b/tests/server-common/pom.xml @@ -30,6 +30,11 @@ ${project.groupId} a2a-java-sdk-server-common + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + jakarta.ws.rs jakarta.ws.rs-api diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java index c456ff3b1..c64e5051c 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/A2AGsonObjectMapper.java @@ -4,8 +4,8 @@ */ package io.a2a.server.apps.common; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.restassured.mapper.ObjectMapper; import io.restassured.mapper.ObjectMapperDeserializationContext; import io.restassured.mapper.ObjectMapperSerializationContext; diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java index 8d52b61b1..de1240c98 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/AbstractA2AServerTest.java @@ -1,5 +1,6 @@ package io.a2a.server.apps.common; +import static io.a2a.spec.A2AMethods.SEND_STREAMING_MESSAGE_METHOD; import static io.a2a.spec.AgentCard.CURRENT_PROTOCOL_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -40,8 +41,13 @@ import io.a2a.client.config.ClientConfig; import io.a2a.grpc.utils.JSONRPCUtils; import io.a2a.grpc.utils.ProtoUtils; -import io.a2a.json.JsonProcessingException; -import io.a2a.json.JsonUtil; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.jsonrpc.common.wrappers.A2AErrorResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import io.a2a.jsonrpc.common.wrappers.StreamingJSONRPCRequest; import io.a2a.spec.A2AClientException; import io.a2a.spec.AgentCapabilities; import io.a2a.spec.AgentCard; @@ -53,7 +59,6 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCErrorResponse; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; @@ -62,9 +67,6 @@ import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.Part; import io.a2a.spec.PushNotificationConfig; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SendStreamingMessageResponse; -import io.a2a.spec.StreamingJSONRPCRequest; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; import io.a2a.spec.TaskIdParams; @@ -269,7 +271,7 @@ public void testListTasksSuccess() throws Exception { try { // Test listing all tasks (no filters) io.a2a.spec.ListTasksParams params = ListTasksParams.builder().tenant("").build(); - io.a2a.spec.ListTasksResult result = getClient().listTasks(params); + ListTasksResult result = getClient().listTasks(params); assertNotNull(result); assertNotNull(result.tasks()); @@ -311,7 +313,7 @@ public void testListTasksFilterByContextId() throws Exception { .contextId("context-filter-1") .tenant("") .build(); - io.a2a.spec.ListTasksResult result = getClient().listTasks(params); + ListTasksResult result = getClient().listTasks(params); assertNotNull(result); assertNotNull(result.tasks()); @@ -352,7 +354,7 @@ public void testListTasksFilterByStatus() throws Exception { .status(TaskState.WORKING) .tenant("") .build(); - io.a2a.spec.ListTasksResult result = getClient().listTasks(params); + ListTasksResult result = getClient().listTasks(params); assertNotNull(result); assertNotNull(result.tasks()); @@ -397,7 +399,7 @@ public void testListTasksWithPagination() throws Exception { .tenant("") .pageSize(2) .build(); - io.a2a.spec.ListTasksResult result1 = getClient().listTasks(params1); + ListTasksResult result1 = getClient().listTasks(params1); assertNotNull(result1); assertEquals(2, result1.tasks().size(), "First page should have 2 tasks"); @@ -411,7 +413,7 @@ public void testListTasksWithPagination() throws Exception { .pageSize(2) .pageToken(result1.nextPageToken()) .build(); - io.a2a.spec.ListTasksResult result2 = getClient().listTasks(params2); + ListTasksResult result2 = getClient().listTasks(params2); assertNotNull(result2); assertTrue(result2.tasks().size() >= 1, "Second page should have at least 1 task"); @@ -447,7 +449,7 @@ public void testListTasksWithHistoryLimit() throws Exception { .tenant("") .historyLength(2) .build(); - io.a2a.spec.ListTasksResult result = getClient().listTasks(params); + ListTasksResult result = getClient().listTasks(params); assertNotNull(result); assertEquals(1, result.tasks().size()); @@ -1419,7 +1421,7 @@ public void testMalformedJSONRPCRequest() { // missing closing bracket String malformedRequest = "{\"jsonrpc\": \"2.0\", \"method\": \"message/send\", \"params\": {\"foo\": \"bar\"}"; - JSONRPCErrorResponse response = given() + A2AErrorResponse response = given() .contentType(MediaType.APPLICATION_JSON) .body(malformedRequest) .when() @@ -1427,7 +1429,7 @@ public void testMalformedJSONRPCRequest() { .then() .statusCode(200) .extract() - .as(JSONRPCErrorResponse.class); + .as(A2AErrorResponse.class); assertNotNull(response.getError()); assertEquals(new JSONParseError().getCode(), response.getError().getCode()); } @@ -1450,7 +1452,7 @@ public void testInvalidParamsJSONRPCRequest() { } private void testInvalidParams(String invalidParamsRequest) { - JSONRPCErrorResponse response = given() + A2AErrorResponse response = given() .contentType(MediaType.APPLICATION_JSON) .body(invalidParamsRequest) .when() @@ -1458,7 +1460,7 @@ private void testInvalidParams(String invalidParamsRequest) { .then() .statusCode(200) .extract() - .as(JSONRPCErrorResponse.class); + .as(A2AErrorResponse.class); assertNotNull(response.getError()); assertEquals(new InvalidParamsError().getCode(), response.getError().getCode()); assertEquals("1", response.getId().toString()); @@ -1476,7 +1478,7 @@ public void testInvalidJSONRPCRequestMissingJsonrpc() { "params": {} } """; - JSONRPCErrorResponse response = given() + A2AErrorResponse response = given() .contentType(MediaType.APPLICATION_JSON) .body(invalidRequest) .when() @@ -1484,7 +1486,7 @@ public void testInvalidJSONRPCRequestMissingJsonrpc() { .then() .statusCode(200) .extract() - .as(JSONRPCErrorResponse.class); + .as(A2AErrorResponse.class); assertNotNull(response.getError()); assertEquals(new InvalidRequestError().getCode(), response.getError().getCode()); } @@ -1498,7 +1500,7 @@ public void testInvalidJSONRPCRequestMissingMethod() { String invalidRequest = """ {"jsonrpc": "2.0", "params": {}} """; - JSONRPCErrorResponse response = given() + A2AErrorResponse response = given() .contentType(MediaType.APPLICATION_JSON) .body(invalidRequest) .when() @@ -1506,7 +1508,7 @@ public void testInvalidJSONRPCRequestMissingMethod() { .then() .statusCode(200) .extract() - .as(JSONRPCErrorResponse.class); + .as(A2AErrorResponse.class); assertNotNull(response.getError()); assertEquals(new InvalidRequestError().getCode(), response.getError().getCode()); } @@ -1520,7 +1522,7 @@ public void testInvalidJSONRPCRequestInvalidId() { String invalidRequest = """ {"jsonrpc": "2.0", "method": "SendMessage", "params": {}, "id": {"bad": "type"}} """; - JSONRPCErrorResponse response = given() + A2AErrorResponse response = given() .contentType(MediaType.APPLICATION_JSON) .body(invalidRequest) .when() @@ -1528,7 +1530,7 @@ public void testInvalidJSONRPCRequestInvalidId() { .then() .statusCode(200) .extract() - .as(JSONRPCErrorResponse.class); + .as(A2AErrorResponse.class); assertNotNull(response.getError()); assertEquals(new InvalidRequestError().getCode(), response.getError().getCode()); } @@ -1542,7 +1544,7 @@ public void testInvalidJSONRPCRequestNonExistentMethod() { String invalidRequest = """ {"jsonrpc": "2.0", "id":"5", "method" : "nonexistent/method", "params": {}} """; - JSONRPCErrorResponse response = given() + A2AErrorResponse response = given() .contentType(MediaType.APPLICATION_JSON) .body(invalidRequest) .when() @@ -1550,7 +1552,7 @@ public void testInvalidJSONRPCRequestNonExistentMethod() { .then() .statusCode(200) .extract() - .as(JSONRPCErrorResponse.class); + .as(A2AErrorResponse.class); assertNotNull(response.getError()); assertEquals(new MethodNotFoundError().getCode(), response.getError().getCode()); } @@ -1694,7 +1696,7 @@ private CompletableFuture>> initialiseStreamingReque .build(); String body = ""; if (request instanceof SendStreamingMessageRequest streamingRequest) { - body = JSONRPCUtils.toJsonRPCRequest((String) streamingRequest.getId(), SendStreamingMessageRequest.METHOD, ProtoUtils.ToProto.sendMessageRequest(streamingRequest.getParams())); + body = JSONRPCUtils.toJsonRPCRequest((String) streamingRequest.getId(), SEND_STREAMING_MESSAGE_METHOD, ProtoUtils.ToProto.sendMessageRequest(streamingRequest.getParams())); } // Create the request diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java index 48daf8517..a77bd30f1 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/AgentExecutorProducer.java @@ -1,15 +1,15 @@ package io.a2a.server.apps.common; +import java.util.List; + import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Produces; -import java.util.List; - import io.a2a.server.agentexecution.AgentExecutor; import io.a2a.server.agentexecution.RequestContext; import io.a2a.server.events.EventQueue; import io.a2a.server.tasks.TaskUpdater; -import io.a2a.spec.JSONRPCError; +import io.a2a.spec.A2AError; import io.a2a.spec.TextPart; import io.a2a.spec.UnsupportedOperationError; import io.quarkus.arc.profile.IfBuildProfile; @@ -22,7 +22,7 @@ public class AgentExecutorProducer { public AgentExecutor agentExecutor() { return new AgentExecutor() { @Override - public void execute(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void execute(RequestContext context, EventQueue eventQueue) throws A2AError { TaskUpdater updater = new TaskUpdater(context, eventQueue); String taskId = context.getTaskId(); @@ -50,7 +50,7 @@ public void execute(RequestContext context, EventQueue eventQueue) throws JSONRP } @Override - public void cancel(RequestContext context, EventQueue eventQueue) throws JSONRPCError { + public void cancel(RequestContext context, EventQueue eventQueue) throws A2AError { if (context.getTask().id().equals("cancel-task-123")) { TaskUpdater taskUpdater = new TaskUpdater(context, eventQueue); taskUpdater.cancel(); diff --git a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java index 7cc62dcfe..9b8214ed7 100644 --- a/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java +++ b/tests/server-common/src/test/java/io/a2a/server/apps/common/TestHttpClient.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; @@ -13,10 +14,9 @@ import io.a2a.client.http.A2AHttpClient; import io.a2a.client.http.A2AHttpResponse; -import io.a2a.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonProcessingException; +import io.a2a.jsonrpc.common.json.JsonUtil; import io.a2a.spec.Task; -import io.a2a.json.JsonUtil; -import java.util.Map; @Dependent @Alternative diff --git a/transport/grpc/pom.xml b/transport/grpc/pom.xml index 6fdf4fc97..6bbb973a4 100644 --- a/transport/grpc/pom.xml +++ b/transport/grpc/pom.xml @@ -32,6 +32,11 @@ ${project.groupId} a2a-java-sdk-spec-grpc + + ${project.groupId} + a2a-java-sdk-jsonrpc-common + ${project.version} + com.google.protobuf protobuf-java diff --git a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java index 1df1409f3..261ee14a8 100644 --- a/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java +++ b/transport/grpc/src/main/java/io/a2a/transport/grpc/handler/GrpcHandler.java @@ -3,8 +3,6 @@ import static io.a2a.grpc.utils.ProtoUtils.FromProto; import static io.a2a.grpc.utils.ProtoUtils.ToProto; -import jakarta.enterprise.inject.Vetoed; - import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -12,23 +10,24 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; - -import io.grpc.Context; import java.util.concurrent.Flow; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; +import jakarta.enterprise.inject.Vetoed; + import com.google.protobuf.Empty; import io.a2a.common.A2AErrorMessages; import io.a2a.grpc.A2AServiceGrpc; import io.a2a.grpc.StreamResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.AgentCardValidator; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.auth.User; import io.a2a.server.extensions.A2AExtensions; -import io.a2a.transport.grpc.context.GrpcContextKeys; import io.a2a.server.requesthandlers.RequestHandler; +import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.ContentTypeNotSupportedError; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; @@ -39,7 +38,6 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.MessageSendParams; @@ -53,6 +51,8 @@ import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; import io.a2a.spec.UnsupportedOperationError; +import io.a2a.transport.grpc.context.GrpcContextKeys; +import io.grpc.Context; import io.grpc.Status; import io.grpc.stub.StreamObserver; @@ -81,7 +81,7 @@ public void sendMessage(io.a2a.grpc.SendMessageRequest request, io.a2a.grpc.SendMessageResponse response = ToProto.taskOrMessage(taskOrMessage); responseObserver.onNext(response); responseObserver.onCompleted(); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -103,7 +103,7 @@ public void getTask(io.a2a.grpc.GetTaskRequest request, } else { handleError(responseObserver, new TaskNotFoundError()); } - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -118,10 +118,10 @@ public void listTasks(io.a2a.grpc.ListTasksRequest request, try { ServerCallContext context = createCallContext(responseObserver); io.a2a.spec.ListTasksParams params = FromProto.listTasksParams(request); - io.a2a.spec.ListTasksResult result = getRequestHandler().onListTasks(params, context); + ListTasksResult result = getRequestHandler().onListTasks(params, context); responseObserver.onNext(ToProto.listTasksResult(result)); responseObserver.onCompleted(); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -143,7 +143,7 @@ public void cancelTask(io.a2a.grpc.CancelTaskRequest request, } else { handleError(responseObserver, new TaskNotFoundError()); } - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -166,7 +166,7 @@ public void setTaskPushNotificationConfig(io.a2a.grpc.SetTaskPushNotificationCon TaskPushNotificationConfig responseConfig = getRequestHandler().onSetTaskPushNotificationConfig(config, context); responseObserver.onNext(ToProto.taskPushNotificationConfig(responseConfig)); responseObserver.onCompleted(); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -189,7 +189,7 @@ public void getTaskPushNotificationConfig(io.a2a.grpc.GetTaskPushNotificationCon TaskPushNotificationConfig config = getRequestHandler().onGetTaskPushNotificationConfig(params, context); responseObserver.onNext(ToProto.taskPushNotificationConfig(config)); responseObserver.onCompleted(); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -213,7 +213,7 @@ public void listTaskPushNotificationConfig(io.a2a.grpc.ListTaskPushNotificationC io.a2a.grpc.ListTaskPushNotificationConfigResponse response = ToProto.listTaskPushNotificationConfigResponse(result); responseObserver.onNext(response); responseObserver.onCompleted(); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -235,7 +235,7 @@ public void sendStreamingMessage(io.a2a.grpc.SendMessageRequest request, MessageSendParams params = FromProto.messageSendParams(request); Flow.Publisher publisher = getRequestHandler().onMessageSendStream(params, context); convertToStreamResponse(publisher, responseObserver); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -257,7 +257,7 @@ public void subscribeToTask(io.a2a.grpc.SubscribeToTaskRequest request, TaskIdParams params = FromProto.taskIdParams(request); Flow.Publisher publisher = getRequestHandler().onResubscribeToTask(params, context); convertToStreamResponse(publisher, responseObserver); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -297,7 +297,7 @@ public void onNext(StreamingEventKind event) { @Override public void onError(Throwable throwable) { - if (throwable instanceof JSONRPCError jsonrpcError) { + if (throwable instanceof A2AError jsonrpcError) { handleError(responseObserver, jsonrpcError); } else { handleInternalError(responseObserver, throwable); @@ -339,7 +339,7 @@ public void deleteTaskPushNotificationConfig(io.a2a.grpc.DeleteTaskPushNotificat // void response responseObserver.onNext(Empty.getDefaultInstance()); responseObserver.onCompleted(); - } catch (JSONRPCError e) { + } catch (A2AError e) { handleError(responseObserver, e); } catch (SecurityException e) { handleSecurityException(responseObserver, e); @@ -405,7 +405,7 @@ private ServerCallContext createCallContext(StreamObserver responseObserv } } - private void handleError(StreamObserver responseObserver, JSONRPCError error) { + private void handleError(StreamObserver responseObserver, A2AError error) { Status status; String description; if (error instanceof InvalidRequestError) { diff --git a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java b/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java index ff165a563..0d8f6fb95 100644 --- a/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java +++ b/transport/grpc/src/test/java/io/a2a/transport/grpc/handler/GrpcHandlerTest.java @@ -25,11 +25,11 @@ import io.a2a.grpc.SendMessageResponse; import io.a2a.grpc.SetTaskPushNotificationConfigRequest; import io.a2a.grpc.StreamResponse; +import io.a2a.grpc.SubscribeToTaskRequest; import io.a2a.grpc.Task; import io.a2a.grpc.TaskPushNotificationConfig; import io.a2a.grpc.TaskState; import io.a2a.grpc.TaskStatus; -import io.a2a.grpc.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.events.EventConsumer; import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; diff --git a/transport/jsonrpc/pom.xml b/transport/jsonrpc/pom.xml index e5cf67dec..c7fa3d9f2 100644 --- a/transport/jsonrpc/pom.xml +++ b/transport/jsonrpc/pom.xml @@ -30,6 +30,11 @@ io.github.a2asdk a2a-java-sdk-spec + + io.github.a2asdk + a2a-java-sdk-jsonrpc-common + ${project.version} + com.google.protobuf protobuf-java-util diff --git a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java index 5c097c04c..6e78f84aa 100644 --- a/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java +++ b/transport/jsonrpc/src/main/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandler.java @@ -2,55 +2,54 @@ import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.Flow; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + +import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; +import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksRequest; +import io.a2a.jsonrpc.common.wrappers.ListTasksResponse; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; +import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.AgentCardValidator; import io.a2a.server.ExtendedAgentCard; import io.a2a.server.PublicAgentCard; import io.a2a.server.ServerCallContext; import io.a2a.server.requesthandlers.RequestHandler; +import io.a2a.server.util.async.Internal; +import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.CancelTaskResponse; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigResponse; import io.a2a.spec.EventKind; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; -import io.a2a.spec.GetAuthenticatedExtendedCardResponse; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.GetTaskResponse; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; -import io.a2a.spec.JSONRPCError; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTaskPushNotificationConfigResponse; import io.a2a.spec.ListTaskPushNotificationConfigResult; -import io.a2a.spec.ListTasksRequest; -import io.a2a.spec.ListTasksResponse; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendMessageResponse; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SendStreamingMessageResponse; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.TaskPushNotificationConfig; -import io.a2a.server.util.async.Internal; -import io.a2a.spec.SubscribeToTaskRequest; import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; @@ -82,7 +81,7 @@ public SendMessageResponse onMessageSend(SendMessageRequest request, ServerCallC try { EventKind taskOrMessage = requestHandler.onMessageSend(request.getParams(), context); return new SendMessageResponse(request.getId(), taskOrMessage); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new SendMessageResponse(request.getId(), e); } catch (Throwable t) { return new SendMessageResponse(request.getId(), new InternalError(t.getMessage())); @@ -105,7 +104,7 @@ public Flow.Publisher onMessageSendStream( // We can't use the convertingProcessor convenience method since that propagates any errors as an error handled // via Subscriber.onError() rather than as part of the SendStreamingResponse payload return convertToSendStreamingMessageResponse(request.getId(), publisher); - } catch (JSONRPCError e) { + } catch (A2AError e) { return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e)); } catch (Throwable throwable) { return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), new InternalError(throwable.getMessage()))); @@ -119,7 +118,7 @@ public CancelTaskResponse onCancelTask(CancelTaskRequest request, ServerCallCont return new CancelTaskResponse(request.getId(), task); } return new CancelTaskResponse(request.getId(), new TaskNotFoundError()); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new CancelTaskResponse(request.getId(), e); } catch (Throwable t) { return new CancelTaskResponse(request.getId(), new InternalError(t.getMessage())); @@ -141,7 +140,7 @@ public Flow.Publisher onSubscribeToTask( // We can't use the convertingProcessor convenience method since that propagates any errors as an error handled // via Subscriber.onError() rather than as part of the SendStreamingResponse payload return convertToSendStreamingMessageResponse(request.getId(), publisher); - } catch (JSONRPCError e) { + } catch (A2AError e) { return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e)); } catch (Throwable throwable) { return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), new InternalError(throwable.getMessage()))); @@ -158,7 +157,7 @@ public GetTaskPushNotificationConfigResponse getPushNotificationConfig( TaskPushNotificationConfig config = requestHandler.onGetTaskPushNotificationConfig(request.getParams(), context); return new GetTaskPushNotificationConfigResponse(request.getId(), config); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new GetTaskPushNotificationConfigResponse(request.getId().toString(), e); } catch (Throwable t) { return new GetTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); @@ -175,7 +174,7 @@ public SetTaskPushNotificationConfigResponse setPushNotificationConfig( TaskPushNotificationConfig config = requestHandler.onSetTaskPushNotificationConfig(request.getParams(), context); return new SetTaskPushNotificationConfigResponse(request.getId().toString(), config); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new SetTaskPushNotificationConfigResponse(request.getId(), e); } catch (Throwable t) { return new SetTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); @@ -186,7 +185,7 @@ public GetTaskResponse onGetTask(GetTaskRequest request, ServerCallContext conte try { Task task = requestHandler.onGetTask(request.getParams(), context); return new GetTaskResponse(request.getId(), task); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new GetTaskResponse(request.getId(), e); } catch (Throwable t) { return new GetTaskResponse(request.getId(), new InternalError(t.getMessage())); @@ -197,7 +196,7 @@ public ListTasksResponse onListTasks(ListTasksRequest request, ServerCallContext try { ListTasksResult result = requestHandler.onListTasks(request.getParams(), context); return new ListTasksResponse(request.getId(), result); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new ListTasksResponse(request.getId(), e); } catch (Throwable t) { return new ListTasksResponse(request.getId(), new InternalError(t.getMessage())); @@ -214,7 +213,7 @@ public ListTaskPushNotificationConfigResponse listPushNotificationConfig( ListTaskPushNotificationConfigResult result = requestHandler.onListTaskPushNotificationConfig(request.getParams(), context); return new ListTaskPushNotificationConfigResponse(request.getId(), result); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new ListTaskPushNotificationConfigResponse(request.getId(), e); } catch (Throwable t) { return new ListTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); @@ -230,7 +229,7 @@ public DeleteTaskPushNotificationConfigResponse deletePushNotificationConfig( try { requestHandler.onDeleteTaskPushNotificationConfig(request.getParams(), context); return new DeleteTaskPushNotificationConfigResponse(request.getId()); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new DeleteTaskPushNotificationConfigResponse(request.getId(), e); } catch (Throwable t) { return new DeleteTaskPushNotificationConfigResponse(request.getId(), new InternalError(t.getMessage())); @@ -246,7 +245,7 @@ public GetAuthenticatedExtendedCardResponse onGetAuthenticatedExtendedCardReques } try { return new GetAuthenticatedExtendedCardResponse(request.getId(), extendedAgentCard.get()); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new GetAuthenticatedExtendedCardResponse(request.getId(), e); } catch (Throwable t) { return new GetAuthenticatedExtendedCardResponse(request.getId(), new InternalError(t.getMessage())); @@ -281,7 +280,7 @@ public void onNext(StreamingEventKind item) { @Override public void onError(Throwable throwable) { - if (throwable instanceof JSONRPCError jsonrpcError) { + if (throwable instanceof A2AError jsonrpcError) { tube.send(new SendStreamingMessageResponse(requestId, jsonrpcError)); } else { tube.send( diff --git a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java b/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java index acf62dcb7..68fc677fe 100644 --- a/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java +++ b/transport/jsonrpc/src/test/java/io/a2a/transport/jsonrpc/handler/JSONRPCHandlerTest.java @@ -17,6 +17,25 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import io.a2a.jsonrpc.common.wrappers.CancelTaskRequest; +import io.a2a.jsonrpc.common.wrappers.CancelTaskResponse; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.DeleteTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardRequest; +import io.a2a.jsonrpc.common.wrappers.GetAuthenticatedExtendedCardResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.GetTaskRequest; +import io.a2a.jsonrpc.common.wrappers.GetTaskResponse; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.ListTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SendMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageRequest; +import io.a2a.jsonrpc.common.wrappers.SendStreamingMessageResponse; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigRequest; +import io.a2a.jsonrpc.common.wrappers.SetTaskPushNotificationConfigResponse; +import io.a2a.jsonrpc.common.wrappers.SubscribeToTaskRequest; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.events.EventConsumer; @@ -27,34 +46,16 @@ import io.a2a.spec.AgentCard; import io.a2a.spec.Artifact; import io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError; -import io.a2a.spec.CancelTaskRequest; -import io.a2a.spec.CancelTaskResponse; import io.a2a.spec.DeleteTaskPushNotificationConfigParams; -import io.a2a.spec.DeleteTaskPushNotificationConfigRequest; -import io.a2a.spec.DeleteTaskPushNotificationConfigResponse; import io.a2a.spec.Event; -import io.a2a.spec.GetAuthenticatedExtendedCardRequest; -import io.a2a.spec.GetAuthenticatedExtendedCardResponse; import io.a2a.spec.GetTaskPushNotificationConfigParams; -import io.a2a.spec.GetTaskPushNotificationConfigRequest; -import io.a2a.spec.GetTaskPushNotificationConfigResponse; -import io.a2a.spec.GetTaskRequest; -import io.a2a.spec.GetTaskResponse; import io.a2a.spec.InternalError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.ListTaskPushNotificationConfigParams; -import io.a2a.spec.ListTaskPushNotificationConfigRequest; -import io.a2a.spec.ListTaskPushNotificationConfigResponse; import io.a2a.spec.Message; import io.a2a.spec.MessageSendParams; import io.a2a.spec.PushNotificationConfig; import io.a2a.spec.PushNotificationNotSupportedError; -import io.a2a.spec.SendMessageRequest; -import io.a2a.spec.SendMessageResponse; -import io.a2a.spec.SendStreamingMessageRequest; -import io.a2a.spec.SendStreamingMessageResponse; -import io.a2a.spec.SetTaskPushNotificationConfigRequest; -import io.a2a.spec.SetTaskPushNotificationConfigResponse; import io.a2a.spec.StreamingEventKind; import io.a2a.spec.Task; import io.a2a.spec.TaskArtifactUpdateEvent; @@ -62,7 +63,6 @@ import io.a2a.spec.TaskNotFoundError; import io.a2a.spec.TaskPushNotificationConfig; import io.a2a.spec.TaskQueryParams; -import io.a2a.spec.SubscribeToTaskRequest; import io.a2a.spec.TaskState; import io.a2a.spec.TaskStatus; import io.a2a.spec.TaskStatusUpdateEvent; diff --git a/transport/rest/pom.xml b/transport/rest/pom.xml index 749f97771..d39b64648 100644 --- a/transport/rest/pom.xml +++ b/transport/rest/pom.xml @@ -30,6 +30,11 @@ io.github.a2asdk a2a-java-sdk-spec + + io.github.a2asdk + a2a-java-sdk-jsonrpc-common + ${project.version} + ${project.groupId} a2a-java-sdk-server-common diff --git a/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java b/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java index ea4d62ec7..ab64cf167 100644 --- a/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java +++ b/transport/rest/src/main/java/io/a2a/transport/rest/handler/RestHandler.java @@ -3,26 +3,34 @@ import static io.a2a.server.util.async.AsyncUtils.createTubeConfig; import static io.a2a.spec.A2AErrorCodes.JSON_PARSE_ERROR_CODE; +import java.time.Instant; +import java.time.format.DateTimeParseException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Flow; +import java.util.logging.Level; +import java.util.logging.Logger; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Instance; +import jakarta.inject.Inject; + import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import io.a2a.grpc.utils.ProtoUtils; +import io.a2a.jsonrpc.common.json.JsonUtil; +import io.a2a.jsonrpc.common.wrappers.ListTasksResult; import io.a2a.server.AgentCardValidator; import io.a2a.server.ExtendedAgentCard; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import java.time.Instant; -import java.time.format.DateTimeParseException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Flow; - import io.a2a.server.PublicAgentCard; import io.a2a.server.ServerCallContext; import io.a2a.server.requesthandlers.RequestHandler; +import io.a2a.server.util.async.Internal; +import io.a2a.spec.A2AError; import io.a2a.spec.AgentCard; import io.a2a.spec.AuthenticatedExtendedCardNotConfiguredError; import io.a2a.spec.ContentTypeNotSupportedError; @@ -34,11 +42,9 @@ import io.a2a.spec.InvalidParamsError; import io.a2a.spec.InvalidRequestError; import io.a2a.spec.JSONParseError; -import io.a2a.spec.JSONRPCError; import io.a2a.spec.ListTaskPushNotificationConfigParams; import io.a2a.spec.ListTaskPushNotificationConfigResult; import io.a2a.spec.ListTasksParams; -import io.a2a.spec.ListTasksResult; import io.a2a.spec.MethodNotFoundError; import io.a2a.spec.PushNotificationNotSupportedError; import io.a2a.spec.StreamingEventKind; @@ -50,13 +56,6 @@ import io.a2a.spec.TaskQueryParams; import io.a2a.spec.TaskState; import io.a2a.spec.UnsupportedOperationError; -import io.a2a.server.util.async.Internal; -import io.a2a.json.JsonUtil; -import jakarta.enterprise.inject.Instance; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.logging.Level; -import java.util.logging.Logger; import mutiny.zero.ZeroPublisher; import org.jspecify.annotations.Nullable; @@ -100,7 +99,7 @@ public HTTPRestResponse sendMessage(String body, String tenant, ServerCallContex request.setTenant(tenant); EventKind result = requestHandler.onMessageSend(ProtoUtils.FromProto.messageSendParams(request), context); return createSuccessResponse(200, io.a2a.grpc.SendMessageResponse.newBuilder(ProtoUtils.ToProto.taskOrMessage(result))); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -117,7 +116,7 @@ public HTTPRestResponse sendStreamingMessage(String body, String tenant, ServerC request.setTenant(tenant); Flow.Publisher publisher = requestHandler.onMessageSendStream(ProtoUtils.FromProto.messageSendParams(request), context); return createStreamingResponse(publisher); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); } catch (Throwable throwable) { return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(new InternalError(throwable.getMessage())).toJson())); @@ -135,7 +134,7 @@ public HTTPRestResponse cancelTask(String taskId, String tenant, ServerCallConte return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); } throw new UnsupportedOperationError(); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -152,7 +151,7 @@ public HTTPRestResponse setTaskPushNotificationConfiguration(String taskId, Stri builder.setTenant(tenant); TaskPushNotificationConfig result = requestHandler.onSetTaskPushNotificationConfig(ProtoUtils.FromProto.setTaskPushNotificationConfig(builder), context); return createSuccessResponse(201, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(result))); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -167,7 +166,7 @@ public HTTPRestResponse subscribeToTask(String taskId, String tenant, ServerCall TaskIdParams params = new TaskIdParams(taskId, tenant); Flow.Publisher publisher = requestHandler.onResubscribeToTask(params, context); return createStreamingResponse(publisher); - } catch (JSONRPCError e) { + } catch (A2AError e) { return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(e).toJson())); } catch (Throwable throwable) { return new HTTPRestStreamingResponse(ZeroPublisher.fromItems(new HTTPRestErrorResponse(new InternalError(throwable.getMessage())).toJson())); @@ -182,7 +181,7 @@ public HTTPRestResponse getTask(String taskId, @Nullable Integer historyLength, return createSuccessResponse(200, io.a2a.grpc.Task.newBuilder(ProtoUtils.ToProto.task(task))); } throw new TaskNotFoundError(); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -230,7 +229,7 @@ public HTTPRestResponse listTasks(@Nullable String contextId, @Nullable String s ListTasksResult result = requestHandler.onListTasks(params, context); return createSuccessResponse(200, io.a2a.grpc.ListTasksResponse.newBuilder(ProtoUtils.ToProto.listTasksResult(result))); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -245,7 +244,7 @@ public HTTPRestResponse getTaskPushNotificationConfiguration(String taskId, @Nul GetTaskPushNotificationConfigParams params = new GetTaskPushNotificationConfigParams(taskId, configId, tenant); TaskPushNotificationConfig config = requestHandler.onGetTaskPushNotificationConfig(params, context); return createSuccessResponse(200, io.a2a.grpc.TaskPushNotificationConfig.newBuilder(ProtoUtils.ToProto.taskPushNotificationConfig(config))); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -260,7 +259,7 @@ public HTTPRestResponse listTaskPushNotificationConfigurations(String taskId, in ListTaskPushNotificationConfigParams params = new ListTaskPushNotificationConfigParams(taskId, pageSize, pageToken, tenant); ListTaskPushNotificationConfigResult result = requestHandler.onListTaskPushNotificationConfig(params, context); return createSuccessResponse(200, io.a2a.grpc.ListTaskPushNotificationConfigResponse.newBuilder(ProtoUtils.ToProto.listTaskPushNotificationConfigResponse(result))); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); @@ -275,14 +274,14 @@ public HTTPRestResponse deleteTaskPushNotificationConfiguration(String taskId, S DeleteTaskPushNotificationConfigParams params = new DeleteTaskPushNotificationConfigParams(taskId, configId, tenant); requestHandler.onDeleteTaskPushNotificationConfig(params, context); return new HTTPRestResponse(204, "application/json", ""); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable throwable) { return createErrorResponse(new InternalError(throwable.getMessage())); } } - private void parseRequestBody(String body, com.google.protobuf.Message.Builder builder) throws JSONRPCError { + private void parseRequestBody(String body, com.google.protobuf.Message.Builder builder) throws A2AError { try { if (body == null || body.trim().isEmpty()) { throw new InvalidRequestError("Request body is required"); @@ -313,12 +312,12 @@ private HTTPRestResponse createSuccessResponse(int statusCode, com.google.protob } } - public HTTPRestResponse createErrorResponse(JSONRPCError error) { + public HTTPRestResponse createErrorResponse(A2AError error) { int statusCode = mapErrorToHttpStatus(error); return createErrorResponse(statusCode, error); } - private HTTPRestResponse createErrorResponse(int statusCode, JSONRPCError error) { + private HTTPRestResponse createErrorResponse(int statusCode, A2AError error) { String jsonBody = new HTTPRestErrorResponse(error).toJson(); return new HTTPRestResponse(statusCode, "application/json", jsonBody); } @@ -358,7 +357,7 @@ public void onNext(StreamingEventKind item) { @Override public void onError(Throwable throwable) { - if (throwable instanceof JSONRPCError jsonrpcError) { + if (throwable instanceof A2AError jsonrpcError) { tube.send(new HTTPRestErrorResponse(jsonrpcError).toJson()); } else { tube.send(new HTTPRestErrorResponse(new InternalError(throwable.getMessage())).toJson()); @@ -375,7 +374,7 @@ public void onComplete() { }); } - private int mapErrorToHttpStatus(JSONRPCError error) { + private int mapErrorToHttpStatus(A2AError error) { if (error instanceof InvalidRequestError || error instanceof JSONParseError) { return 400; } @@ -409,7 +408,7 @@ public HTTPRestResponse getExtendedAgentCard(String tenant) { throw new AuthenticatedExtendedCardNotConfiguredError(null, "Authenticated Extended Card not configured", null); } return new HTTPRestResponse(200, "application/json", JsonUtil.toJson(extendedAgentCard.get())); - } catch (JSONRPCError e) { + } catch (A2AError e) { return createErrorResponse(e); } catch (Throwable t) { return createErrorResponse(500, new InternalError(t.getMessage())); @@ -474,7 +473,7 @@ private static class HTTPRestErrorResponse { private final @Nullable String message; - private HTTPRestErrorResponse(JSONRPCError jsonRpcError) { + private HTTPRestErrorResponse(A2AError jsonRpcError) { this.error = jsonRpcError.getClass().getName(); this.message = jsonRpcError.getMessage(); } diff --git a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java b/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java index 5b309116d..9dd4e9cdb 100644 --- a/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java +++ b/transport/rest/src/test/java/io/a2a/transport/rest/handler/RestHandlerTest.java @@ -1,19 +1,19 @@ package io.a2a.transport.rest.handler; -import com.google.protobuf.InvalidProtocolBufferException; import java.util.HashSet; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Flow; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import com.google.protobuf.InvalidProtocolBufferException; import io.a2a.server.ServerCallContext; import io.a2a.server.auth.UnauthenticatedUser; import io.a2a.server.requesthandlers.AbstractA2ARequestHandlerTest; +import io.a2a.server.tasks.TaskUpdater; import io.a2a.spec.AgentCard; import io.a2a.spec.Task; -import io.a2a.server.tasks.TaskUpdater; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Flow; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test;